Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'amd-drm-next-6.19-2025-12-02' of https://gitlab.freedesktop.org/agd5f/linux into drm-next

amd-drm-next-6.19-2025-12-02:

amdgpu:
- Unified MES fix
- SMU 11 unbalanced irq fix
- Fix for driver reloading on APUs
- pp_table sysfs fix
- Fix memory leak in fence handling
- HDMI fix
- DC cursor fixes
- eDP panel parsing fix
- Brightness fix
- DC analog fixes
- EDID retry fixes
- UserQ fixes
- RAS fixes
- IP discovery fix
- Add missing locking in amdgpu_ttm_access_memory_sdma()
- Smart Power OLED fix
- PRT and page fault fixes for GC 6-8
- VMID reservation fix
- ACP platform device fix
- Add missing vm fault handling for GC 11-12
- VPE fix

amdkfd:
- Partitioning fix

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20251202220101.2039347-1-alexander.deucher@amd.com

+1972 -184
+8 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
··· 302 302 adev->acp.acp_res[2].end = adev->acp.acp_res[2].start; 303 303 304 304 adev->acp.acp_cell[0].name = "acp_audio_dma"; 305 + adev->acp.acp_cell[0].id = 0; 305 306 adev->acp.acp_cell[0].num_resources = 3; 306 307 adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0]; 307 308 adev->acp.acp_cell[0].platform_data = &adev->asic_type; 308 309 adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type); 309 310 310 311 adev->acp.acp_cell[1].name = "designware-i2s"; 312 + adev->acp.acp_cell[1].id = 1; 311 313 adev->acp.acp_cell[1].num_resources = 1; 312 314 adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1]; 313 315 adev->acp.acp_cell[1].platform_data = &i2s_pdata[0]; 314 316 adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data); 315 - r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, 2); 317 + r = mfd_add_devices(adev->acp.parent, 0, adev->acp.acp_cell, 2, NULL, 0, NULL); 316 318 if (r) 317 319 goto failure; 318 320 r = device_for_each_child(adev->acp.parent, &adev->acp.acp_genpd->gpd, ··· 412 410 adev->acp.acp_res[4].end = adev->acp.acp_res[4].start; 413 411 414 412 adev->acp.acp_cell[0].name = "acp_audio_dma"; 413 + adev->acp.acp_cell[0].id = 0; 415 414 adev->acp.acp_cell[0].num_resources = 5; 416 415 adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0]; 417 416 adev->acp.acp_cell[0].platform_data = &adev->asic_type; 418 417 adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type); 419 418 420 419 adev->acp.acp_cell[1].name = "designware-i2s"; 420 + adev->acp.acp_cell[1].id = 1; 421 421 adev->acp.acp_cell[1].num_resources = 1; 422 422 adev->acp.acp_cell[1].resources = &adev->acp.acp_res[1]; 423 423 adev->acp.acp_cell[1].platform_data = &i2s_pdata[0]; 424 424 adev->acp.acp_cell[1].pdata_size = sizeof(struct i2s_platform_data); 425 425 426 426 adev->acp.acp_cell[2].name = "designware-i2s"; 427 + adev->acp.acp_cell[2].id = 2; 427 428 adev->acp.acp_cell[2].num_resources = 1; 428 429 adev->acp.acp_cell[2].resources = &adev->acp.acp_res[2]; 429 430 adev->acp.acp_cell[2].platform_data = &i2s_pdata[1]; 430 431 adev->acp.acp_cell[2].pdata_size = sizeof(struct i2s_platform_data); 431 432 432 433 adev->acp.acp_cell[3].name = "designware-i2s"; 434 + adev->acp.acp_cell[3].id = 3; 433 435 adev->acp.acp_cell[3].num_resources = 1; 434 436 adev->acp.acp_cell[3].resources = &adev->acp.acp_res[3]; 435 437 adev->acp.acp_cell[3].platform_data = &i2s_pdata[2]; 436 438 adev->acp.acp_cell[3].pdata_size = sizeof(struct i2s_platform_data); 437 439 438 - r = mfd_add_hotplug_devices(adev->acp.parent, adev->acp.acp_cell, ACP_DEVS); 440 + r = mfd_add_devices(adev->acp.parent, 0, adev->acp.acp_cell, ACP_DEVS, NULL, 0, NULL); 439 441 if (r) 440 442 goto failure; 441 443
+16
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 2665 2665 chip_name = "navi12"; 2666 2666 break; 2667 2667 case CHIP_CYAN_SKILLFISH: 2668 + if (adev->discovery.bin) 2669 + return 0; 2668 2670 chip_name = "cyan_skillfish"; 2669 2671 break; 2670 2672 } ··· 3680 3678 if (amdgpu_virt_release_full_gpu(adev, false)) 3681 3679 dev_err(adev->dev, 3682 3680 "failed to release exclusive mode on fini\n"); 3681 + } 3682 + 3683 + /* 3684 + * Driver reload on the APU can fail due to firmware validation because 3685 + * the PSP is always running, as it is shared across the whole SoC. 3686 + * This same issue does not occur on dGPU because it has a mechanism 3687 + * that checks whether the PSP is running. A solution for those issues 3688 + * in the APU is to trigger a GPU reset, but this should be done during 3689 + * the unload phase to avoid adding boot latency and screen flicker. 3690 + */ 3691 + if ((adev->flags & AMD_IS_APU) && !adev->gmc.is_app_apu) { 3692 + r = amdgpu_asic_reset(adev); 3693 + if (r) 3694 + dev_err(adev->dev, "asic reset on %s failed\n", __func__); 3683 3695 } 3684 3696 3685 3697 return 0;
+3
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
··· 597 597 /* reserve engine 5 for firmware */ 598 598 if (adev->enable_mes) 599 599 vm_inv_engs[i] &= ~(1 << 5); 600 + /* reserve engine 6 for uni mes */ 601 + if (adev->enable_uni_mes) 602 + vm_inv_engs[i] &= ~(1 << 6); 600 603 /* reserve mmhub engine 3 for firmware */ 601 604 if (adev->enable_umsch_mm) 602 605 vm_inv_engs[i] &= ~(1 << 3);
+5
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h
··· 86 86 87 87 #define AMDGPU_MAX_MEM_RANGES 8 88 88 89 + #define AMDGPU_GMC9_FAULT_SOURCE_DATA_RETRY 0x80 90 + #define AMDGPU_GMC9_FAULT_SOURCE_DATA_READ 0x40 91 + #define AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE 0x20 92 + #define AMDGPU_GMC9_FAULT_SOURCE_DATA_EXE 0x10 93 + 89 94 /* 90 95 * GMC page fault information 91 96 */
+4
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
··· 224 224 kfree((*job)->hw_fence); 225 225 err_job: 226 226 kfree(*job); 227 + *job = NULL; 227 228 228 229 return r; 229 230 } ··· 246 245 if (r) { 247 246 if (entity) 248 247 drm_sched_job_cleanup(&(*job)->base); 248 + kfree((*job)->hw_vm_fence); 249 + kfree((*job)->hw_fence); 249 250 kfree(*job); 251 + *job = NULL; 250 252 } 251 253 252 254 return r;
+27 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
··· 150 150 151 151 #ifdef CONFIG_X86_MCE_AMD 152 152 static void amdgpu_register_bad_pages_mca_notifier(struct amdgpu_device *adev); 153 + static void 154 + amdgpu_unregister_bad_pages_mca_notifier(struct amdgpu_device *adev); 153 155 struct mce_notifier_adev_list { 154 156 struct amdgpu_device *devs[MAX_GPU_INSTANCE]; 155 157 int num_gpu; ··· 3956 3954 mutex_unlock(&con->recovery_lock); 3957 3955 3958 3956 amdgpu_ras_critical_region_init(adev); 3959 - 3957 + #ifdef CONFIG_X86_MCE_AMD 3958 + amdgpu_unregister_bad_pages_mca_notifier(adev); 3959 + #endif 3960 3960 return 0; 3961 3961 } 3962 3962 /* recovery end */ ··· 4990 4986 if (notifier_registered == false) { 4991 4987 mce_register_decode_chain(&amdgpu_bad_page_nb); 4992 4988 notifier_registered = true; 4989 + } 4990 + } 4991 + static void amdgpu_unregister_bad_pages_mca_notifier(struct amdgpu_device *adev) 4992 + { 4993 + int i, j; 4994 + 4995 + if (!notifier_registered && !mce_adev_list.num_gpu) 4996 + return; 4997 + for (i = 0, j = 0; i < mce_adev_list.num_gpu; i++) { 4998 + if (mce_adev_list.devs[i] == adev) 4999 + mce_adev_list.devs[i] = NULL; 5000 + if (!mce_adev_list.devs[i]) 5001 + ++j; 5002 + } 5003 + 5004 + if (j == mce_adev_list.num_gpu) { 5005 + mce_adev_list.num_gpu = 0; 5006 + /* Unregister x86 notifier with MCE subsystem. */ 5007 + if (notifier_registered) { 5008 + mce_unregister_decode_chain(&amdgpu_bad_page_nb); 5009 + notifier_registered = false; 5010 + } 4993 5011 } 4994 5012 } 4995 5013 #endif
+5
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
··· 520 520 return -ENOMEM; 521 521 522 522 if (!(*offset)) { 523 + /* Need at least 12 bytes for the header on the first read */ 524 + if (size < ring_header_size) 525 + return -EINVAL; 526 + 523 527 if (copy_to_user(buf, ring_header, ring_header_size)) 524 528 return -EFAULT; 525 529 buf += ring_header_size; 530 + size -= ring_header_size; 526 531 } 527 532 528 533 r = amdgpu_ras_mgr_handle_ras_cmd(ring->adev,
+3 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
··· 1329 1329 mem->mem_type == AMDGPU_PL_MMIO_REMAP)) { 1330 1330 flags |= AMDGPU_PTE_SYSTEM; 1331 1331 1332 - if (ttm->caching == ttm_cached) 1332 + if (ttm && ttm->caching == ttm_cached) 1333 1333 flags |= AMDGPU_PTE_SNOOPED; 1334 1334 } 1335 1335 ··· 1486 1486 if (r) 1487 1487 goto out; 1488 1488 1489 + mutex_lock(&adev->mman.gtt_window_lock); 1489 1490 amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm); 1490 1491 src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + 1491 1492 src_mm.start; ··· 1501 1500 WARN_ON(job->ibs[0].length_dw > num_dw); 1502 1501 1503 1502 fence = amdgpu_job_submit(job); 1503 + mutex_unlock(&adev->mman.gtt_window_lock); 1504 1504 1505 1505 if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout)) 1506 1506 r = -ETIMEDOUT;
+4 -5
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
··· 1069 1069 } 1070 1070 1071 1071 /* Prepare a TLB flush fence to be attached to PTs */ 1072 - if (!params->unlocked && vm->is_compute_context) { 1072 + if (!params->unlocked) { 1073 1073 amdgpu_vm_tlb_fence_create(params->adev, vm, fence); 1074 1074 1075 1075 /* Makes sure no PD/PT is freed before the flush */ ··· 2093 2093 struct amdgpu_bo *bo = before->bo_va->base.bo; 2094 2094 2095 2095 amdgpu_vm_it_insert(before, &vm->va); 2096 - if (before->flags & AMDGPU_PTE_PRT_FLAG(adev)) 2096 + if (before->flags & AMDGPU_VM_PAGE_PRT) 2097 2097 amdgpu_vm_prt_get(adev); 2098 2098 2099 2099 if (amdgpu_vm_is_bo_always_valid(vm, bo) && ··· 2108 2108 struct amdgpu_bo *bo = after->bo_va->base.bo; 2109 2109 2110 2110 amdgpu_vm_it_insert(after, &vm->va); 2111 - if (after->flags & AMDGPU_PTE_PRT_FLAG(adev)) 2111 + if (after->flags & AMDGPU_VM_PAGE_PRT) 2112 2112 amdgpu_vm_prt_get(adev); 2113 2113 2114 2114 if (amdgpu_vm_is_bo_always_valid(vm, bo) && ··· 2916 2916 switch (args->in.op) { 2917 2917 case AMDGPU_VM_OP_RESERVE_VMID: 2918 2918 /* We only have requirement to reserve vmid from gfxhub */ 2919 - amdgpu_vmid_alloc_reserved(adev, vm, AMDGPU_GFXHUB(0)); 2920 - break; 2919 + return amdgpu_vmid_alloc_reserved(adev, vm, AMDGPU_GFXHUB(0)); 2921 2920 case AMDGPU_VM_OP_UNRESERVE_VMID: 2922 2921 amdgpu_vmid_free_reserved(adev, vm, AMDGPU_GFXHUB(0)); 2923 2922 break;
+12
drivers/gpu/drm/amd/amdgpu/cik_ih.c
··· 156 156 /* enable irqs */ 157 157 cik_ih_enable_interrupts(adev); 158 158 159 + if (adev->irq.ih_soft.ring_size) 160 + adev->irq.ih_soft.enabled = true; 161 + 159 162 return 0; 160 163 } 161 164 ··· 195 192 196 193 wptr = le32_to_cpu(*ih->wptr_cpu); 197 194 195 + if (ih == &adev->irq.ih_soft) 196 + goto out; 197 + 198 198 if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { 199 199 wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK; 200 200 /* When a ring buffer overflow happen start parsing interrupt ··· 217 211 tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; 218 212 WREG32(mmIH_RB_CNTL, tmp); 219 213 } 214 + 215 + out: 220 216 return (wptr & ih->ptr_mask); 221 217 } 222 218 ··· 311 303 struct amdgpu_device *adev = ip_block->adev; 312 304 313 305 r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, false); 306 + if (r) 307 + return r; 308 + 309 + r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true); 314 310 if (r) 315 311 return r; 316 312
+10
drivers/gpu/drm/amd/amdgpu/cz_ih.c
··· 157 157 /* enable interrupts */ 158 158 cz_ih_enable_interrupts(adev); 159 159 160 + if (adev->irq.ih_soft.ring_size) 161 + adev->irq.ih_soft.enabled = true; 162 + 160 163 return 0; 161 164 } 162 165 ··· 196 193 u32 wptr, tmp; 197 194 198 195 wptr = le32_to_cpu(*ih->wptr_cpu); 196 + 197 + if (ih == &adev->irq.ih_soft) 198 + goto out; 199 199 200 200 if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) 201 201 goto out; ··· 300 294 struct amdgpu_device *adev = ip_block->adev; 301 295 302 296 r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, false); 297 + if (r) 298 + return r; 299 + 300 + r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true); 303 301 if (r) 304 302 return r; 305 303
+2 -2
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
··· 5874 5874 if (flags & AMDGPU_IB_PREEMPTED) 5875 5875 control |= INDIRECT_BUFFER_PRE_RESUME(1); 5876 5876 5877 - if (vmid) 5877 + if (vmid && !ring->adev->gfx.rs64_enable) 5878 5878 gfx_v11_0_ring_emit_de_meta(ring, 5879 - (!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false); 5879 + !amdgpu_sriov_vf(ring->adev) && (flags & AMDGPU_IB_PREEMPTED)); 5880 5880 } 5881 5881 5882 5882 amdgpu_ring_write(ring, header);
+4 -2
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
··· 103 103 uint32_t vmhub_index = entry->client_id == SOC15_IH_CLIENTID_VMC ? 104 104 AMDGPU_MMHUB0(0) : AMDGPU_GFXHUB(0); 105 105 struct amdgpu_vmhub *hub = &adev->vmhub[vmhub_index]; 106 - bool retry_fault = !!(entry->src_data[1] & 0x80); 107 - bool write_fault = !!(entry->src_data[1] & 0x20); 106 + bool retry_fault = !!(entry->src_data[1] & 107 + AMDGPU_GMC9_FAULT_SOURCE_DATA_RETRY); 108 + bool write_fault = !!(entry->src_data[1] & 109 + AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE); 108 110 struct amdgpu_task_info *task_info; 109 111 uint32_t status = 0; 110 112 u64 addr;
+29
drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
··· 103 103 uint32_t vmhub_index = entry->client_id == SOC21_IH_CLIENTID_VMC ? 104 104 AMDGPU_MMHUB0(0) : AMDGPU_GFXHUB(0); 105 105 struct amdgpu_vmhub *hub = &adev->vmhub[vmhub_index]; 106 + bool retry_fault = !!(entry->src_data[1] & 107 + AMDGPU_GMC9_FAULT_SOURCE_DATA_RETRY); 108 + bool write_fault = !!(entry->src_data[1] & 109 + AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE); 106 110 uint32_t status = 0; 107 111 u64 addr; 108 112 109 113 addr = (u64)entry->src_data[0] << 12; 110 114 addr |= ((u64)entry->src_data[1] & 0xf) << 44; 115 + 116 + if (retry_fault) { 117 + /* Returning 1 here also prevents sending the IV to the KFD */ 118 + 119 + /* Process it only if it's the first fault for this address */ 120 + if (entry->ih != &adev->irq.ih_soft && 121 + amdgpu_gmc_filter_faults(adev, entry->ih, addr, entry->pasid, 122 + entry->timestamp)) 123 + return 1; 124 + 125 + /* Delegate it to a different ring if the hardware hasn't 126 + * already done it. 127 + */ 128 + if (entry->ih == &adev->irq.ih) { 129 + amdgpu_irq_delegate(adev, entry, 8); 130 + return 1; 131 + } 132 + 133 + /* Try to handle the recoverable page faults by filling page 134 + * tables 135 + */ 136 + if (amdgpu_vm_handle_fault(adev, entry->pasid, 0, 0, addr, 137 + entry->timestamp, write_fault)) 138 + return 1; 139 + } 111 140 112 141 if (!amdgpu_sriov_vf(adev)) { 113 142 /*
+29
drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c
··· 91 91 struct amdgpu_iv_entry *entry) 92 92 { 93 93 struct amdgpu_vmhub *hub; 94 + bool retry_fault = !!(entry->src_data[1] & 95 + AMDGPU_GMC9_FAULT_SOURCE_DATA_RETRY); 96 + bool write_fault = !!(entry->src_data[1] & 97 + AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE); 94 98 uint32_t status = 0; 95 99 u64 addr; 96 100 ··· 105 101 hub = &adev->vmhub[AMDGPU_MMHUB0(0)]; 106 102 else 107 103 hub = &adev->vmhub[AMDGPU_GFXHUB(0)]; 104 + 105 + if (retry_fault) { 106 + /* Returning 1 here also prevents sending the IV to the KFD */ 107 + 108 + /* Process it only if it's the first fault for this address */ 109 + if (entry->ih != &adev->irq.ih_soft && 110 + amdgpu_gmc_filter_faults(adev, entry->ih, addr, entry->pasid, 111 + entry->timestamp)) 112 + return 1; 113 + 114 + /* Delegate it to a different ring if the hardware hasn't 115 + * already done it. 116 + */ 117 + if (entry->ih == &adev->irq.ih) { 118 + amdgpu_irq_delegate(adev, entry, 8); 119 + return 1; 120 + } 121 + 122 + /* Try to handle the recoverable page faults by filling page 123 + * tables 124 + */ 125 + if (amdgpu_vm_handle_fault(adev, entry->pasid, 0, 0, addr, 126 + entry->timestamp, write_fault)) 127 + return 1; 128 + } 108 129 109 130 if (!amdgpu_sriov_vf(adev)) { 110 131 /*
+14 -6
drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c
··· 610 610 } 611 611 612 612 static void gmc_v6_0_vm_decode_fault(struct amdgpu_device *adev, 613 - u32 status, u32 addr, u32 mc_client) 613 + u32 status, u32 addr) 614 614 { 615 615 u32 mc_id; 616 616 u32 vmid = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, VMID); 617 617 u32 protections = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, 618 618 PROTECTIONS); 619 - char block[5] = { mc_client >> 24, (mc_client >> 16) & 0xff, 620 - (mc_client >> 8) & 0xff, mc_client & 0xff, 0 }; 621 619 622 620 mc_id = REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, 623 621 MEMORY_CLIENT_ID); 624 622 625 - dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from '%s' (0x%08x) (%d)\n", 623 + dev_err(adev->dev, "VM fault (0x%02x, vmid %d) at page %u, %s from %d\n", 626 624 protections, vmid, addr, 627 625 REG_GET_FIELD(status, VM_CONTEXT1_PROTECTION_FAULT_STATUS, 628 626 MEMORY_CLIENT_RW) ? 629 - "write" : "read", block, mc_client, mc_id); 627 + "write" : "read", mc_id); 630 628 } 631 629 632 630 static const u32 mc_cg_registers[] = { ··· 1070 1072 { 1071 1073 u32 addr, status; 1072 1074 1075 + /* Delegate to the soft IRQ handler ring */ 1076 + if (adev->irq.ih_soft.enabled && entry->ih != &adev->irq.ih_soft) { 1077 + amdgpu_irq_delegate(adev, entry, 4); 1078 + return 1; 1079 + } 1080 + 1073 1081 addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR); 1074 1082 status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS); 1075 1083 WREG32_P(mmVM_CONTEXT1_CNTL2, 1, ~1); 1076 1084 1077 1085 if (!addr && !status) 1078 1086 return 0; 1087 + 1088 + amdgpu_vm_update_fault_cache(adev, entry->pasid, 1089 + ((u64)addr) << AMDGPU_GPU_PAGE_SHIFT, 1090 + status, AMDGPU_GFXHUB(0)); 1079 1091 1080 1092 if (amdgpu_vm_fault_stop == AMDGPU_VM_FAULT_STOP_FIRST) 1081 1093 gmc_v6_0_set_fault_enable_default(adev, false); ··· 1097 1089 addr); 1098 1090 dev_err(adev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", 1099 1091 status); 1100 - gmc_v6_0_vm_decode_fault(adev, status, addr, 0); 1092 + gmc_v6_0_vm_decode_fault(adev, status, addr); 1101 1093 } 1102 1094 1103 1095 return 0;
+6
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
··· 1261 1261 { 1262 1262 u32 addr, status, mc_client, vmid; 1263 1263 1264 + /* Delegate to the soft IRQ handler ring */ 1265 + if (adev->irq.ih_soft.enabled && entry->ih != &adev->irq.ih_soft) { 1266 + amdgpu_irq_delegate(adev, entry, 4); 1267 + return 1; 1268 + } 1269 + 1264 1270 addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR); 1265 1271 status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS); 1266 1272 mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
+6
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
··· 1439 1439 return 0; 1440 1440 } 1441 1441 1442 + /* Delegate to the soft IRQ handler ring */ 1443 + if (adev->irq.ih_soft.enabled && entry->ih != &adev->irq.ih_soft) { 1444 + amdgpu_irq_delegate(adev, entry, 4); 1445 + return 1; 1446 + } 1447 + 1442 1448 addr = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_ADDR); 1443 1449 status = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_STATUS); 1444 1450 mc_client = RREG32(mmVM_CONTEXT1_PROTECTION_FAULT_MCCLIENT);
+4 -2
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
··· 544 544 struct amdgpu_irq_src *source, 545 545 struct amdgpu_iv_entry *entry) 546 546 { 547 - bool retry_fault = !!(entry->src_data[1] & 0x80); 548 - bool write_fault = !!(entry->src_data[1] & 0x20); 547 + bool retry_fault = !!(entry->src_data[1] & 548 + AMDGPU_GMC9_FAULT_SOURCE_DATA_RETRY); 549 + bool write_fault = !!(entry->src_data[1] & 550 + AMDGPU_GMC9_FAULT_SOURCE_DATA_WRITE); 549 551 uint32_t status = 0, cid = 0, rw = 0, fed = 0; 550 552 struct amdgpu_task_info *task_info; 551 553 struct amdgpu_vmhub *hub;
+10
drivers/gpu/drm/amd/amdgpu/iceland_ih.c
··· 157 157 /* enable interrupts */ 158 158 iceland_ih_enable_interrupts(adev); 159 159 160 + if (adev->irq.ih_soft.ring_size) 161 + adev->irq.ih_soft.enabled = true; 162 + 160 163 return 0; 161 164 } 162 165 ··· 196 193 u32 wptr, tmp; 197 194 198 195 wptr = le32_to_cpu(*ih->wptr_cpu); 196 + 197 + if (ih == &adev->irq.ih_soft) 198 + goto out; 199 199 200 200 if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) 201 201 goto out; ··· 299 293 struct amdgpu_device *adev = ip_block->adev; 300 294 301 295 r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, false); 296 + if (r) 297 + return r; 298 + 299 + r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true); 302 300 if (r) 303 301 return r; 304 302
+1 -1
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
··· 1390 1390 adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; 1391 1391 break; 1392 1392 case IP_VERSION(6, 0, 3): 1393 - if ((adev->sdma.instance[0].fw_version >= 27) && !adev->sdma.disable_uq) 1393 + if (adev->sdma.instance[0].fw_version >= 29 && !adev->sdma.disable_uq) 1394 1394 adev->userq_funcs[AMDGPU_HW_IP_DMA] = &userq_mes_funcs; 1395 1395 break; 1396 1396 case IP_VERSION(6, 1, 0):
+12
drivers/gpu/drm/amd/amdgpu/si_ih.c
··· 96 96 pci_set_master(adev->pdev); 97 97 si_ih_enable_interrupts(adev); 98 98 99 + if (adev->irq.ih_soft.ring_size) 100 + adev->irq.ih_soft.enabled = true; 101 + 99 102 return 0; 100 103 } 101 104 ··· 115 112 116 113 wptr = le32_to_cpu(*ih->wptr_cpu); 117 114 115 + if (ih == &adev->irq.ih_soft) 116 + goto out; 117 + 118 118 if (wptr & IH_RB_WPTR__RB_OVERFLOW_MASK) { 119 119 wptr &= ~IH_RB_WPTR__RB_OVERFLOW_MASK; 120 120 dev_warn(adev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", ··· 133 127 tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK; 134 128 WREG32(IH_RB_CNTL, tmp); 135 129 } 130 + 131 + out: 136 132 return (wptr & ih->ptr_mask); 137 133 } 138 134 ··· 180 172 struct amdgpu_device *adev = ip_block->adev; 181 173 182 174 r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, false); 175 + if (r) 176 + return r; 177 + 178 + r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true); 183 179 if (r) 184 180 return r; 185 181
-4
drivers/gpu/drm/amd/amdgpu/soc15.c
··· 853 853 { 854 854 u32 sol_reg; 855 855 856 - /* CP hangs in IGT reloading test on RN, reset to WA */ 857 - if (adev->asic_type == CHIP_RENOIR) 858 - return true; 859 - 860 856 if (amdgpu_gmc_need_reset_on_init(adev)) 861 857 return true; 862 858 if (amdgpu_psp_tos_reload_needed(adev))
+10
drivers/gpu/drm/amd/amdgpu/tonga_ih.c
··· 159 159 /* enable interrupts */ 160 160 tonga_ih_enable_interrupts(adev); 161 161 162 + if (adev->irq.ih_soft.ring_size) 163 + adev->irq.ih_soft.enabled = true; 164 + 162 165 return 0; 163 166 } 164 167 ··· 198 195 u32 wptr, tmp; 199 196 200 197 wptr = le32_to_cpu(*ih->wptr_cpu); 198 + 199 + if (ih == &adev->irq.ih_soft) 200 + goto out; 201 201 202 202 if (!REG_GET_FIELD(wptr, IH_RB_WPTR, RB_OVERFLOW)) 203 203 goto out; ··· 309 303 struct amdgpu_device *adev = ip_block->adev; 310 304 311 305 r = amdgpu_ih_ring_init(adev, &adev->irq.ih, 64 * 1024, true); 306 + if (r) 307 + return r; 308 + 309 + r = amdgpu_ih_ring_init(adev, &adev->irq.ih_soft, IH_SW_RING_SIZE, true); 312 310 if (r) 313 311 return r; 314 312
+1 -1
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
··· 141 141 adev->vcn.supported_reset = 142 142 amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]); 143 143 144 - if (amdgpu_dpm_reset_vcn_is_supported(adev)) 144 + if (amdgpu_dpm_reset_vcn_is_supported(adev) && !amdgpu_sriov_vf(adev)) 145 145 adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; 146 146 147 147 return 0;
+3 -1
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
··· 122 122 123 123 switch (amdgpu_ip_version(adev, MP0_HWIP, 0)) { 124 124 case IP_VERSION(13, 0, 12): 125 - if ((adev->psp.sos.fw_version >= 0x00450025) && amdgpu_dpm_reset_vcn_is_supported(adev)) 125 + if ((adev->psp.sos.fw_version >= 0x00450025) && 126 + amdgpu_dpm_reset_vcn_is_supported(adev) && 127 + !amdgpu_sriov_vf(adev)) 126 128 adev->vcn.supported_reset |= AMDGPU_RESET_TYPE_PER_QUEUE; 127 129 break; 128 130 default:
+3 -1
drivers/gpu/drm/amd/amdkfd/kfd_topology.c
··· 530 530 sysfs_show_32bit_prop(buffer, offs, "sdma_fw_version", 531 531 dev->gpu->kfd->sdma_fw_version); 532 532 sysfs_show_64bit_prop(buffer, offs, "unique_id", 533 - dev->gpu->xcp ? 533 + dev->gpu->xcp && 534 + (dev->gpu->xcp->xcp_mgr->mode != 535 + AMDGPU_SPX_PARTITION_MODE) ? 534 536 dev->gpu->xcp->unique_id : 535 537 dev->gpu->adev->unique_id); 536 538 sysfs_show_32bit_prop(buffer, offs, "num_xcc",
+167 -6
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 3932 3932 mutex_unlock(&dev->mode_config.mutex); 3933 3933 } 3934 3934 3935 + static bool are_sinks_equal(const struct dc_sink *sink1, const struct dc_sink *sink2) 3936 + { 3937 + if (!sink1 || !sink2) 3938 + return false; 3939 + if (sink1->sink_signal != sink2->sink_signal) 3940 + return false; 3941 + 3942 + if (sink1->dc_edid.length != sink2->dc_edid.length) 3943 + return false; 3944 + 3945 + if (memcmp(sink1->dc_edid.raw_edid, sink2->dc_edid.raw_edid, 3946 + sink1->dc_edid.length) != 0) 3947 + return false; 3948 + return true; 3949 + } 3950 + 3951 + 3952 + /** 3953 + * DOC: hdmi_hpd_debounce_work 3954 + * 3955 + * HDMI HPD debounce delay in milliseconds. When an HDMI display toggles HPD 3956 + * (such as during power save transitions), this delay determines how long to 3957 + * wait before processing the HPD event. This allows distinguishing between a 3958 + * physical unplug (>hdmi_hpd_debounce_delay) 3959 + * and a spontaneous RX HPD toggle (<hdmi_hpd_debounce_delay). 3960 + * 3961 + * If the toggle is less than this delay, the driver compares sink capabilities 3962 + * and permits a hotplug event if they changed. 3963 + * 3964 + * The default value of 1500ms was chosen based on experimental testing with 3965 + * various monitors that exhibit spontaneous HPD toggling behavior. 3966 + */ 3967 + static void hdmi_hpd_debounce_work(struct work_struct *work) 3968 + { 3969 + struct amdgpu_dm_connector *aconnector = 3970 + container_of(to_delayed_work(work), struct amdgpu_dm_connector, 3971 + hdmi_hpd_debounce_work); 3972 + struct drm_connector *connector = &aconnector->base; 3973 + struct drm_device *dev = connector->dev; 3974 + struct amdgpu_device *adev = drm_to_adev(dev); 3975 + struct dc *dc = aconnector->dc_link->ctx->dc; 3976 + bool fake_reconnect = false; 3977 + bool reallow_idle = false; 3978 + bool ret = false; 3979 + guard(mutex)(&aconnector->hpd_lock); 3980 + 3981 + /* Re-detect the display */ 3982 + scoped_guard(mutex, &adev->dm.dc_lock) { 3983 + if (dc->caps.ips_support && dc->ctx->dmub_srv->idle_allowed) { 3984 + dc_allow_idle_optimizations(dc, false); 3985 + reallow_idle = true; 3986 + } 3987 + ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); 3988 + } 3989 + 3990 + if (ret) { 3991 + /* Apply workaround delay for certain panels */ 3992 + apply_delay_after_dpcd_poweroff(adev, aconnector->dc_sink); 3993 + /* Compare sinks to determine if this was a spontaneous HPD toggle */ 3994 + if (are_sinks_equal(aconnector->dc_link->local_sink, aconnector->hdmi_prev_sink)) { 3995 + /* 3996 + * Sinks match - this was a spontaneous HDMI HPD toggle. 3997 + */ 3998 + drm_dbg_kms(dev, "HDMI HPD: Sink unchanged after debounce, internal re-enable\n"); 3999 + fake_reconnect = true; 4000 + } 4001 + 4002 + /* Update connector state */ 4003 + amdgpu_dm_update_connector_after_detect(aconnector); 4004 + 4005 + drm_modeset_lock_all(dev); 4006 + dm_restore_drm_connector_state(dev, connector); 4007 + drm_modeset_unlock_all(dev); 4008 + 4009 + /* Only notify OS if sink actually changed */ 4010 + if (!fake_reconnect && aconnector->base.force == DRM_FORCE_UNSPECIFIED) 4011 + drm_kms_helper_hotplug_event(dev); 4012 + } 4013 + 4014 + /* Release the cached sink reference */ 4015 + if (aconnector->hdmi_prev_sink) { 4016 + dc_sink_release(aconnector->hdmi_prev_sink); 4017 + aconnector->hdmi_prev_sink = NULL; 4018 + } 4019 + 4020 + scoped_guard(mutex, &adev->dm.dc_lock) { 4021 + if (reallow_idle && dc->caps.ips_support) 4022 + dc_allow_idle_optimizations(dc, true); 4023 + } 4024 + } 4025 + 3935 4026 static void handle_hpd_irq_helper(struct amdgpu_dm_connector *aconnector) 3936 4027 { 3937 4028 struct drm_connector *connector = &aconnector->base; ··· 4032 3941 struct dm_connector_state *dm_con_state = to_dm_connector_state(connector->state); 4033 3942 struct dc *dc = aconnector->dc_link->ctx->dc; 4034 3943 bool ret = false; 3944 + bool debounce_required = false; 4035 3945 4036 3946 if (adev->dm.disable_hpd_irq) 4037 3947 return; ··· 4055 3963 if (!dc_link_detect_connection_type(aconnector->dc_link, &new_connection_type)) 4056 3964 drm_err(adev_to_drm(adev), "KMS: Failed to detect connector\n"); 4057 3965 3966 + /* 3967 + * Check for HDMI disconnect with debounce enabled. 3968 + */ 3969 + debounce_required = (aconnector->hdmi_hpd_debounce_delay_ms > 0 && 3970 + dc_is_hdmi_signal(aconnector->dc_link->connector_signal) && 3971 + new_connection_type == dc_connection_none && 3972 + aconnector->dc_link->local_sink != NULL); 3973 + 4058 3974 if (aconnector->base.force && new_connection_type == dc_connection_none) { 4059 3975 emulated_link_detect(aconnector->dc_link); 4060 3976 ··· 4072 3972 4073 3973 if (aconnector->base.force == DRM_FORCE_UNSPECIFIED) 4074 3974 drm_kms_helper_connector_hotplug_event(connector); 3975 + } else if (debounce_required) { 3976 + /* 3977 + * HDMI disconnect detected - schedule delayed work instead of 3978 + * processing immediately. This allows us to coalesce spurious 3979 + * HDMI signals from physical unplugs. 3980 + */ 3981 + drm_dbg_kms(dev, "HDMI HPD: Disconnect detected, scheduling debounce work (%u ms)\n", 3982 + aconnector->hdmi_hpd_debounce_delay_ms); 3983 + 3984 + /* Cache the current sink for later comparison */ 3985 + if (aconnector->hdmi_prev_sink) 3986 + dc_sink_release(aconnector->hdmi_prev_sink); 3987 + aconnector->hdmi_prev_sink = aconnector->dc_link->local_sink; 3988 + if (aconnector->hdmi_prev_sink) 3989 + dc_sink_retain(aconnector->hdmi_prev_sink); 3990 + 3991 + /* Schedule delayed detection. */ 3992 + if (mod_delayed_work(system_wq, 3993 + &aconnector->hdmi_hpd_debounce_work, 3994 + msecs_to_jiffies(aconnector->hdmi_hpd_debounce_delay_ms))) 3995 + drm_dbg_kms(dev, "HDMI HPD: Re-scheduled debounce work\n"); 3996 + 4075 3997 } else { 3998 + 3999 + /* If the aconnector->hdmi_hpd_debounce_work is scheduled, exit early */ 4000 + if (delayed_work_pending(&aconnector->hdmi_hpd_debounce_work)) 4001 + return; 4002 + 4076 4003 scoped_guard(mutex, &adev->dm.dc_lock) { 4077 4004 dc_exit_ips_for_hw_access(dc); 4078 4005 ret = dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD); ··· 5125 4998 struct dc_link *link; 5126 4999 u32 brightness; 5127 5000 bool rc, reallow_idle = false; 5001 + struct drm_connector *connector; 5002 + 5003 + list_for_each_entry(connector, &dm->ddev->mode_config.connector_list, head) { 5004 + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); 5005 + 5006 + if (aconnector->bl_idx != bl_idx) 5007 + continue; 5008 + 5009 + /* if connector is off, save the brightness for next time it's on */ 5010 + if (!aconnector->base.encoder) { 5011 + dm->brightness[bl_idx] = user_brightness; 5012 + dm->actual_brightness[bl_idx] = 0; 5013 + return; 5014 + } 5015 + } 5128 5016 5129 5017 amdgpu_dm_update_backlight_caps(dm, bl_idx); 5130 5018 caps = &dm->backlight_caps[bl_idx]; ··· 7736 7594 if (aconnector->mst_mgr.dev) 7737 7595 drm_dp_mst_topology_mgr_destroy(&aconnector->mst_mgr); 7738 7596 7597 + /* Cancel and flush any pending HDMI HPD debounce work */ 7598 + cancel_delayed_work_sync(&aconnector->hdmi_hpd_debounce_work); 7599 + if (aconnector->hdmi_prev_sink) { 7600 + dc_sink_release(aconnector->hdmi_prev_sink); 7601 + aconnector->hdmi_prev_sink = NULL; 7602 + } 7603 + 7739 7604 if (aconnector->bl_idx != -1) { 7740 7605 backlight_device_unregister(dm->backlight_dev[aconnector->bl_idx]); 7741 7606 dm->backlight_dev[aconnector->bl_idx] = NULL; ··· 8839 8690 if (!(amdgpu_freesync_vid_mode && drm_edid)) 8840 8691 return; 8841 8692 8842 - if (!amdgpu_dm_connector->dc_sink || amdgpu_dm_connector->dc_sink->edid_caps.analog || 8843 - !dc_supports_vrr(amdgpu_dm_connector->dc_sink->ctx->dce_version)) 8693 + if (!amdgpu_dm_connector->dc_sink || !amdgpu_dm_connector->dc_link) 8694 + return; 8695 + 8696 + if (!dc_supports_vrr(amdgpu_dm_connector->dc_sink->ctx->dce_version)) 8697 + return; 8698 + 8699 + if (dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id) && 8700 + amdgpu_dm_connector->dc_sink->edid_caps.analog) 8844 8701 return; 8845 8702 8846 8703 if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) ··· 8858 8703 { 8859 8704 struct amdgpu_dm_connector *amdgpu_dm_connector = 8860 8705 to_amdgpu_dm_connector(connector); 8706 + struct dc_link *dc_link = amdgpu_dm_connector->dc_link; 8861 8707 struct drm_encoder *encoder; 8862 8708 const struct drm_edid *drm_edid = amdgpu_dm_connector->drm_edid; 8863 - struct dc_link_settings *verified_link_cap = 8864 - &amdgpu_dm_connector->dc_link->verified_link_cap; 8865 - const struct dc *dc = amdgpu_dm_connector->dc_link->dc; 8709 + struct dc_link_settings *verified_link_cap = &dc_link->verified_link_cap; 8710 + const struct dc *dc = dc_link->dc; 8866 8711 8867 8712 encoder = amdgpu_dm_connector_to_encoder(connector); 8868 8713 ··· 8873 8718 amdgpu_dm_connector->num_modes += 8874 8719 drm_add_modes_noedid(connector, 1920, 1080); 8875 8720 8876 - if (amdgpu_dm_connector->dc_sink && amdgpu_dm_connector->dc_sink->edid_caps.analog) { 8721 + if (amdgpu_dm_connector->dc_sink && 8722 + amdgpu_dm_connector->dc_sink->edid_caps.analog && 8723 + dc_connector_supports_analog(dc_link->link_id.id)) { 8877 8724 /* Analog monitor connected by DAC load detection. 8878 8725 * Add common modes. It will be up to the user to select one that works. 8879 8726 */ ··· 8929 8772 memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info)); 8930 8773 mutex_init(&aconnector->hpd_lock); 8931 8774 mutex_init(&aconnector->handle_mst_msg_ready); 8775 + 8776 + aconnector->hdmi_hpd_debounce_delay_ms = AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS; 8777 + INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work); 8778 + aconnector->hdmi_prev_sink = NULL; 8932 8779 8933 8780 /* 8934 8781 * configure support HPD hot plug connector_>polled default value is 0
+6
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
··· 59 59 60 60 #define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL) 61 61 62 + #define AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS 1500 62 63 /* 63 64 #include "include/amdgpu_dal_power_if.h" 64 65 #include "amdgpu_dm_irq.h" ··· 820 819 bool pack_sdp_v1_3; 821 820 enum adaptive_sync_type as_type; 822 821 struct amdgpu_hdmi_vsdb_info vsdb_info; 822 + 823 + /* HDMI HPD debounce support */ 824 + unsigned int hdmi_hpd_debounce_delay_ms; 825 + struct delayed_work hdmi_hpd_debounce_work; 826 + struct dc_sink *hdmi_prev_sink; 823 827 }; 824 828 825 829 static inline void amdgpu_dm_set_mst_status(uint8_t *status,
+4 -4
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
··· 998 998 struct amdgpu_dm_connector *aconnector = link->priv; 999 999 struct drm_connector *connector = &aconnector->base; 1000 1000 struct i2c_adapter *ddc; 1001 - int retry = 3; 1002 - enum dc_edid_status edid_status; 1001 + int retry = 25; 1002 + enum dc_edid_status edid_status = EDID_NO_RESPONSE; 1003 1003 const struct drm_edid *drm_edid; 1004 1004 const struct edid *edid; 1005 1005 ··· 1029 1029 } 1030 1030 1031 1031 if (!drm_edid) 1032 - return EDID_NO_RESPONSE; 1032 + continue; 1033 1033 1034 1034 edid = drm_edid_raw(drm_edid); // FIXME: Get rid of drm_edid_raw() 1035 1035 if (!edid || ··· 1047 1047 &sink->dc_edid, 1048 1048 &sink->edid_caps); 1049 1049 1050 - } while (edid_status == EDID_BAD_CHECKSUM && --retry > 0); 1050 + } while ((edid_status == EDID_BAD_CHECKSUM || edid_status == EDID_NO_RESPONSE) && --retry > 0); 1051 1051 1052 1052 if (edid_status != EDID_OK) 1053 1053 DRM_ERROR("EDID err: %d, on connector: %s",
+23 -36
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
··· 884 884 }; 885 885 886 886 #if defined(CONFIG_DRM_AMD_DC_FP) 887 - static uint16_t get_fec_overhead_multiplier(struct dc_link *dc_link) 887 + static uint64_t kbps_to_pbn(int kbps, bool is_peak_pbn) 888 888 { 889 - u8 link_coding_cap; 890 - uint16_t fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B; 889 + uint64_t effective_kbps = (uint64_t)kbps; 891 890 892 - link_coding_cap = dc_link_dp_mst_decide_link_encoding_format(dc_link); 893 - if (link_coding_cap == DP_128b_132b_ENCODING) 894 - fec_overhead_multiplier_x1000 = PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B; 891 + if (is_peak_pbn) { // add 0.6% (1006/1000) overhead into effective kbps 892 + effective_kbps *= 1006; 893 + effective_kbps = div_u64(effective_kbps, 1000); 894 + } 895 895 896 - return fec_overhead_multiplier_x1000; 896 + return (uint64_t) DIV64_U64_ROUND_UP(effective_kbps * 64, (54 * 8 * 1000)); 897 897 } 898 898 899 - static int kbps_to_peak_pbn(int kbps, uint16_t fec_overhead_multiplier_x1000) 899 + static uint32_t pbn_to_kbps(unsigned int pbn, bool with_margin) 900 900 { 901 - u64 peak_kbps = kbps; 901 + uint64_t pbn_effective = (uint64_t)pbn; 902 902 903 - peak_kbps *= 1006; 904 - peak_kbps *= fec_overhead_multiplier_x1000; 905 - peak_kbps = div_u64(peak_kbps, 1000 * 1000); 906 - return (int) DIV64_U64_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000)); 903 + if (with_margin) // deduct 0.6% (994/1000) overhead from effective pbn 904 + pbn_effective *= (1000000 / PEAK_FACTOR_X1000); 905 + else 906 + pbn_effective *= 1000; 907 + 908 + return DIV_U64_ROUND_UP(pbn_effective * 8 * 54, 64); 907 909 } 908 910 909 911 static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *params, ··· 976 974 dc_dsc_get_default_config_option(param.sink->ctx->dc, &dsc_options); 977 975 dsc_options.max_target_bpp_limit_override_x16 = drm_connector->display_info.max_dsc_bpp * 16; 978 976 979 - kbps = div_u64((u64)pbn * 994 * 8 * 54, 64); 977 + kbps = pbn_to_kbps(pbn, false); 980 978 dc_dsc_compute_config( 981 979 param.sink->ctx->dc->res_pool->dscs[0], 982 980 &param.sink->dsc_caps.dsc_dec_caps, ··· 1005 1003 int link_timeslots_used; 1006 1004 int fair_pbn_alloc; 1007 1005 int ret = 0; 1008 - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); 1009 1006 1010 1007 for (i = 0; i < count; i++) { 1011 1008 if (vars[i + k].dsc_enabled) { 1012 1009 initial_slack[i] = 1013 - kbps_to_peak_pbn(params[i].bw_range.max_kbps, fec_overhead_multiplier_x1000) - vars[i + k].pbn; 1010 + kbps_to_pbn(params[i].bw_range.max_kbps, false) - vars[i + k].pbn; 1014 1011 bpp_increased[i] = false; 1015 1012 remaining_to_increase += 1; 1016 1013 } else { ··· 1105 1104 int next_index; 1106 1105 int remaining_to_try = 0; 1107 1106 int ret; 1108 - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); 1109 1107 int var_pbn; 1110 1108 1111 1109 for (i = 0; i < count; i++) { ··· 1137 1137 1138 1138 DRM_DEBUG_DRIVER("MST_DSC index #%d, try no compression\n", next_index); 1139 1139 var_pbn = vars[next_index].pbn; 1140 - vars[next_index].pbn = kbps_to_peak_pbn(params[next_index].bw_range.stream_kbps, fec_overhead_multiplier_x1000); 1140 + vars[next_index].pbn = kbps_to_pbn(params[next_index].bw_range.stream_kbps, true); 1141 1141 ret = drm_dp_atomic_find_time_slots(state, 1142 1142 params[next_index].port->mgr, 1143 1143 params[next_index].port, ··· 1197 1197 int count = 0; 1198 1198 int i, k, ret; 1199 1199 bool debugfs_overwrite = false; 1200 - uint16_t fec_overhead_multiplier_x1000 = get_fec_overhead_multiplier(dc_link); 1201 1200 struct drm_connector_state *new_conn_state; 1202 1201 1203 1202 memset(params, 0, sizeof(params)); ··· 1277 1278 DRM_DEBUG_DRIVER("MST_DSC Try no compression\n"); 1278 1279 for (i = 0; i < count; i++) { 1279 1280 vars[i + k].aconnector = params[i].aconnector; 1280 - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); 1281 + vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false); 1281 1282 vars[i + k].dsc_enabled = false; 1282 1283 vars[i + k].bpp_x16 = 0; 1283 1284 ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, params[i].port, ··· 1299 1300 DRM_DEBUG_DRIVER("MST_DSC Try max compression\n"); 1300 1301 for (i = 0; i < count; i++) { 1301 1302 if (params[i].compression_possible && params[i].clock_force_enable != DSC_CLK_FORCE_DISABLE) { 1302 - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.min_kbps, fec_overhead_multiplier_x1000); 1303 + vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.min_kbps, false); 1303 1304 vars[i + k].dsc_enabled = true; 1304 1305 vars[i + k].bpp_x16 = params[i].bw_range.min_target_bpp_x16; 1305 1306 ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, ··· 1307 1308 if (ret < 0) 1308 1309 return ret; 1309 1310 } else { 1310 - vars[i + k].pbn = kbps_to_peak_pbn(params[i].bw_range.stream_kbps, fec_overhead_multiplier_x1000); 1311 + vars[i + k].pbn = kbps_to_pbn(params[i].bw_range.stream_kbps, false); 1311 1312 vars[i + k].dsc_enabled = false; 1312 1313 vars[i + k].bpp_x16 = 0; 1313 1314 ret = drm_dp_atomic_find_time_slots(state, params[i].port->mgr, ··· 1762 1763 return ret; 1763 1764 } 1764 1765 1765 - static uint32_t kbps_from_pbn(unsigned int pbn) 1766 - { 1767 - uint64_t kbps = (uint64_t)pbn; 1768 - 1769 - kbps *= (1000000 / PEAK_FACTOR_X1000); 1770 - kbps *= 8; 1771 - kbps *= 54; 1772 - kbps /= 64; 1773 - 1774 - return (uint32_t)kbps; 1775 - } 1776 - 1777 1766 static bool is_dsc_common_config_possible(struct dc_stream_state *stream, 1778 1767 struct dc_dsc_bw_range *bw_range) 1779 1768 { ··· 1860 1873 dc_link_get_highest_encoding_format(stream->link)); 1861 1874 cur_link_settings = stream->link->verified_link_cap; 1862 1875 root_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, &cur_link_settings); 1863 - virtual_channel_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn); 1876 + virtual_channel_bw_in_kbps = pbn_to_kbps(aconnector->mst_output_port->full_pbn, true); 1864 1877 1865 1878 /* pick the end to end bw bottleneck */ 1866 1879 end_to_end_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps); ··· 1913 1926 immediate_upstream_port = aconnector->mst_output_port->parent->port_parent; 1914 1927 1915 1928 if (immediate_upstream_port) { 1916 - virtual_channel_bw_in_kbps = kbps_from_pbn(immediate_upstream_port->full_pbn); 1929 + virtual_channel_bw_in_kbps = pbn_to_kbps(immediate_upstream_port->full_pbn, true); 1917 1930 virtual_channel_bw_in_kbps = min(root_link_bw_in_kbps, virtual_channel_bw_in_kbps); 1918 1931 } else { 1919 1932 /* For topology LCT 1 case - only one mstb*/
+1 -1
drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
··· 805 805 806 806 if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) 807 807 device_id_mask = ATOM_S0_CRT1_MASK; 808 - else if (bp_params.device_id == ATOM_DEVICE_CRT1_SUPPORT) 808 + else if (bp_params.device_id == ATOM_DEVICE_CRT2_SUPPORT) 809 809 device_id_mask = ATOM_S0_CRT2_MASK; 810 810 else 811 811 return BP_RESULT_UNSUPPORTED;
+4 -4
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
··· 1480 1480 /* not provided by VBIOS */ 1481 1481 info->lcd_timing.misc_info.HORIZONTAL_CUT_OFF = 0; 1482 1482 1483 - info->lcd_timing.misc_info.H_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo 1484 - & ATOM_HSYNC_POLARITY); 1485 - info->lcd_timing.misc_info.V_SYNC_POLARITY = ~(uint32_t) (lvds->lcd_timing.miscinfo 1486 - & ATOM_VSYNC_POLARITY); 1483 + info->lcd_timing.misc_info.H_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo & 1484 + ATOM_HSYNC_POLARITY); 1485 + info->lcd_timing.misc_info.V_SYNC_POLARITY = !(lvds->lcd_timing.miscinfo & 1486 + ATOM_VSYNC_POLARITY); 1487 1487 1488 1488 /* not provided by VBIOS */ 1489 1489 info->lcd_timing.misc_info.VERTICAL_CUT_OFF = 0;
+576
drivers/gpu/drm/amd/display/dc/core/dc.c
··· 303 303 link->link_id.id = CONNECTOR_ID_VIRTUAL; 304 304 link->link_id.enum_id = ENUM_ID_1; 305 305 link->psr_settings.psr_version = DC_PSR_VERSION_UNSUPPORTED; 306 + link->replay_settings.config.replay_version = DC_REPLAY_VERSION_UNSUPPORTED; 306 307 link->link_enc = kzalloc(sizeof(*link->link_enc), GFP_KERNEL); 307 308 308 309 if (!link->link_enc) { ··· 2147 2146 if (!dcb->funcs->is_accelerated_mode(dcb)) { 2148 2147 disable_vbios_mode_if_required(dc, context); 2149 2148 dc->hwss.enable_accelerated_mode(dc, context); 2149 + } else if (get_seamless_boot_stream_count(dc->current_state) > 0) { 2150 + /* If the previous Stream still retains the apply seamless boot flag, 2151 + * it means the OS has not actually performed a flip yet. 2152 + * At this point, if we receive dc_commit_streams again, we should 2153 + * once more check whether the actual HW timing matches what the OS 2154 + * has provided 2155 + */ 2156 + disable_vbios_mode_if_required(dc, context); 2150 2157 } 2151 2158 2152 2159 if (dc->hwseq->funcs.wait_for_pipe_update_if_needed) { ··· 6012 6003 if (pipe_ctx) 6013 6004 otg_inst = pipe_ctx->stream_res.tg->inst; 6014 6005 6006 + // before enable smart power OLED, we need to call set pipe for DMUB to set ABM config 6007 + if (enable) { 6008 + if (dc->hwss.set_pipe && pipe_ctx) 6009 + dc->hwss.set_pipe(pipe_ctx); 6010 + } 6011 + 6015 6012 // fill in cmd 6016 6013 memset(&cmd, 0, sizeof(cmd)); 6017 6014 ··· 6524 6509 { 6525 6510 out_data->uclk_p_state = dc->current_state->clk_mgr->clks.p_state_change_support; 6526 6511 out_data->fams = dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching; 6512 + } 6513 + 6514 + bool dc_capture_register_software_state(struct dc *dc, struct dc_register_software_state *state) 6515 + { 6516 + struct dc_state *context; 6517 + struct resource_context *res_ctx; 6518 + int i; 6519 + 6520 + if (!dc || !dc->current_state || !state) { 6521 + if (state) 6522 + state->state_valid = false; 6523 + return false; 6524 + } 6525 + 6526 + /* Initialize the state structure */ 6527 + memset(state, 0, sizeof(struct dc_register_software_state)); 6528 + 6529 + context = dc->current_state; 6530 + res_ctx = &context->res_ctx; 6531 + 6532 + /* Count active pipes and streams */ 6533 + state->active_pipe_count = 0; 6534 + state->active_stream_count = context->stream_count; 6535 + 6536 + for (i = 0; i < dc->res_pool->pipe_count; i++) { 6537 + if (res_ctx->pipe_ctx[i].stream) 6538 + state->active_pipe_count++; 6539 + } 6540 + 6541 + /* Capture HUBP programming state for each pipe */ 6542 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6543 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6544 + 6545 + state->hubp[i].valid_stream = false; 6546 + if (!pipe_ctx->stream) 6547 + continue; 6548 + 6549 + state->hubp[i].valid_stream = true; 6550 + 6551 + /* HUBP register programming variables */ 6552 + if (pipe_ctx->stream_res.tg) 6553 + state->hubp[i].vtg_sel = pipe_ctx->stream_res.tg->inst; 6554 + 6555 + state->hubp[i].hubp_clock_enable = (pipe_ctx->plane_res.hubp != NULL) ? 1 : 0; 6556 + 6557 + state->hubp[i].valid_plane_state = false; 6558 + if (pipe_ctx->plane_state) { 6559 + state->hubp[i].valid_plane_state = true; 6560 + state->hubp[i].surface_pixel_format = pipe_ctx->plane_state->format; 6561 + state->hubp[i].rotation_angle = pipe_ctx->plane_state->rotation; 6562 + state->hubp[i].h_mirror_en = pipe_ctx->plane_state->horizontal_mirror ? 1 : 0; 6563 + 6564 + /* Surface size */ 6565 + if (pipe_ctx->plane_state->plane_size.surface_size.width > 0) { 6566 + state->hubp[i].surface_size_width = pipe_ctx->plane_state->plane_size.surface_size.width; 6567 + state->hubp[i].surface_size_height = pipe_ctx->plane_state->plane_size.surface_size.height; 6568 + } 6569 + 6570 + /* Viewport dimensions from scaler data */ 6571 + if (pipe_ctx->plane_state->src_rect.width > 0) { 6572 + state->hubp[i].pri_viewport_width = pipe_ctx->plane_state->src_rect.width; 6573 + state->hubp[i].pri_viewport_height = pipe_ctx->plane_state->src_rect.height; 6574 + state->hubp[i].pri_viewport_x_start = pipe_ctx->plane_state->src_rect.x; 6575 + state->hubp[i].pri_viewport_y_start = pipe_ctx->plane_state->src_rect.y; 6576 + } 6577 + 6578 + /* DCC settings */ 6579 + state->hubp[i].surface_dcc_en = (pipe_ctx->plane_state->dcc.enable) ? 1 : 0; 6580 + state->hubp[i].surface_dcc_ind_64b_blk = pipe_ctx->plane_state->dcc.independent_64b_blks; 6581 + state->hubp[i].surface_dcc_ind_128b_blk = pipe_ctx->plane_state->dcc.dcc_ind_blk; 6582 + 6583 + /* Surface pitch */ 6584 + state->hubp[i].surface_pitch = pipe_ctx->plane_state->plane_size.surface_pitch; 6585 + state->hubp[i].meta_pitch = pipe_ctx->plane_state->dcc.meta_pitch; 6586 + state->hubp[i].chroma_pitch = pipe_ctx->plane_state->plane_size.chroma_pitch; 6587 + state->hubp[i].meta_pitch_c = pipe_ctx->plane_state->dcc.meta_pitch_c; 6588 + 6589 + /* Surface addresses - primary */ 6590 + state->hubp[i].primary_surface_address_low = pipe_ctx->plane_state->address.grph.addr.low_part; 6591 + state->hubp[i].primary_surface_address_high = pipe_ctx->plane_state->address.grph.addr.high_part; 6592 + state->hubp[i].primary_meta_surface_address_low = pipe_ctx->plane_state->address.grph.meta_addr.low_part; 6593 + state->hubp[i].primary_meta_surface_address_high = pipe_ctx->plane_state->address.grph.meta_addr.high_part; 6594 + 6595 + /* TMZ settings */ 6596 + state->hubp[i].primary_surface_tmz = pipe_ctx->plane_state->address.tmz_surface; 6597 + state->hubp[i].primary_meta_surface_tmz = pipe_ctx->plane_state->address.tmz_surface; 6598 + 6599 + /* Tiling configuration */ 6600 + state->hubp[i].min_dc_gfx_version9 = false; 6601 + if (pipe_ctx->plane_state->tiling_info.gfxversion >= DcGfxVersion9) { 6602 + state->hubp[i].min_dc_gfx_version9 = true; 6603 + state->hubp[i].sw_mode = pipe_ctx->plane_state->tiling_info.gfx9.swizzle; 6604 + state->hubp[i].num_pipes = pipe_ctx->plane_state->tiling_info.gfx9.num_pipes; 6605 + state->hubp[i].num_banks = pipe_ctx->plane_state->tiling_info.gfx9.num_banks; 6606 + state->hubp[i].pipe_interleave = pipe_ctx->plane_state->tiling_info.gfx9.pipe_interleave; 6607 + state->hubp[i].num_shader_engines = pipe_ctx->plane_state->tiling_info.gfx9.num_shader_engines; 6608 + state->hubp[i].num_rb_per_se = pipe_ctx->plane_state->tiling_info.gfx9.num_rb_per_se; 6609 + state->hubp[i].num_pkrs = pipe_ctx->plane_state->tiling_info.gfx9.num_pkrs; 6610 + } 6611 + } 6612 + 6613 + /* DML Request Size Configuration */ 6614 + if (pipe_ctx->rq_regs.rq_regs_l.chunk_size > 0) { 6615 + state->hubp[i].rq_chunk_size = pipe_ctx->rq_regs.rq_regs_l.chunk_size; 6616 + state->hubp[i].rq_min_chunk_size = pipe_ctx->rq_regs.rq_regs_l.min_chunk_size; 6617 + state->hubp[i].rq_meta_chunk_size = pipe_ctx->rq_regs.rq_regs_l.meta_chunk_size; 6618 + state->hubp[i].rq_min_meta_chunk_size = pipe_ctx->rq_regs.rq_regs_l.min_meta_chunk_size; 6619 + state->hubp[i].rq_dpte_group_size = pipe_ctx->rq_regs.rq_regs_l.dpte_group_size; 6620 + state->hubp[i].rq_mpte_group_size = pipe_ctx->rq_regs.rq_regs_l.mpte_group_size; 6621 + state->hubp[i].rq_swath_height_l = pipe_ctx->rq_regs.rq_regs_l.swath_height; 6622 + state->hubp[i].rq_pte_row_height_l = pipe_ctx->rq_regs.rq_regs_l.pte_row_height_linear; 6623 + } 6624 + 6625 + /* Chroma request size configuration */ 6626 + if (pipe_ctx->rq_regs.rq_regs_c.chunk_size > 0) { 6627 + state->hubp[i].rq_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.chunk_size; 6628 + state->hubp[i].rq_min_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.min_chunk_size; 6629 + state->hubp[i].rq_meta_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.meta_chunk_size; 6630 + state->hubp[i].rq_min_meta_chunk_size_c = pipe_ctx->rq_regs.rq_regs_c.min_meta_chunk_size; 6631 + state->hubp[i].rq_dpte_group_size_c = pipe_ctx->rq_regs.rq_regs_c.dpte_group_size; 6632 + state->hubp[i].rq_mpte_group_size_c = pipe_ctx->rq_regs.rq_regs_c.mpte_group_size; 6633 + state->hubp[i].rq_swath_height_c = pipe_ctx->rq_regs.rq_regs_c.swath_height; 6634 + state->hubp[i].rq_pte_row_height_c = pipe_ctx->rq_regs.rq_regs_c.pte_row_height_linear; 6635 + } 6636 + 6637 + /* DML expansion modes */ 6638 + state->hubp[i].drq_expansion_mode = pipe_ctx->rq_regs.drq_expansion_mode; 6639 + state->hubp[i].prq_expansion_mode = pipe_ctx->rq_regs.prq_expansion_mode; 6640 + state->hubp[i].mrq_expansion_mode = pipe_ctx->rq_regs.mrq_expansion_mode; 6641 + state->hubp[i].crq_expansion_mode = pipe_ctx->rq_regs.crq_expansion_mode; 6642 + 6643 + /* DML DLG parameters - nominal */ 6644 + state->hubp[i].dst_y_per_vm_vblank = pipe_ctx->dlg_regs.dst_y_per_vm_vblank; 6645 + state->hubp[i].dst_y_per_row_vblank = pipe_ctx->dlg_regs.dst_y_per_row_vblank; 6646 + state->hubp[i].dst_y_per_vm_flip = pipe_ctx->dlg_regs.dst_y_per_vm_flip; 6647 + state->hubp[i].dst_y_per_row_flip = pipe_ctx->dlg_regs.dst_y_per_row_flip; 6648 + 6649 + /* DML prefetch settings */ 6650 + state->hubp[i].dst_y_prefetch = pipe_ctx->dlg_regs.dst_y_prefetch; 6651 + state->hubp[i].vratio_prefetch = pipe_ctx->dlg_regs.vratio_prefetch; 6652 + state->hubp[i].vratio_prefetch_c = pipe_ctx->dlg_regs.vratio_prefetch_c; 6653 + 6654 + /* TTU parameters */ 6655 + state->hubp[i].qos_level_low_wm = pipe_ctx->ttu_regs.qos_level_low_wm; 6656 + state->hubp[i].qos_level_high_wm = pipe_ctx->ttu_regs.qos_level_high_wm; 6657 + state->hubp[i].qos_level_flip = pipe_ctx->ttu_regs.qos_level_flip; 6658 + state->hubp[i].min_ttu_vblank = pipe_ctx->ttu_regs.min_ttu_vblank; 6659 + } 6660 + 6661 + /* Capture HUBBUB programming state */ 6662 + if (dc->res_pool->hubbub) { 6663 + /* Individual DET buffer sizes - software state variables that program DET registers */ 6664 + for (i = 0; i < 4 && i < dc->res_pool->pipe_count; i++) { 6665 + uint32_t det_size = res_ctx->pipe_ctx[i].det_buffer_size_kb; 6666 + switch (i) { 6667 + case 0: 6668 + state->hubbub.det0_size = det_size; 6669 + break; 6670 + case 1: 6671 + state->hubbub.det1_size = det_size; 6672 + break; 6673 + case 2: 6674 + state->hubbub.det2_size = det_size; 6675 + break; 6676 + case 3: 6677 + state->hubbub.det3_size = det_size; 6678 + break; 6679 + } 6680 + } 6681 + 6682 + /* Compression buffer configuration - software state that programs COMPBUF_SIZE register */ 6683 + // TODO: Handle logic for legacy DCN pre-DCN401 6684 + state->hubbub.compbuf_size = context->bw_ctx.bw.dcn.arb_regs.compbuf_size; 6685 + } 6686 + 6687 + /* Capture DPP programming state for each pipe */ 6688 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6689 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6690 + 6691 + if (!pipe_ctx->stream) 6692 + continue; 6693 + 6694 + state->dpp[i].dpp_clock_enable = (pipe_ctx->plane_res.dpp != NULL) ? 1 : 0; 6695 + 6696 + if (pipe_ctx->plane_state && pipe_ctx->plane_res.scl_data.recout.width > 0) { 6697 + /* Access dscl_prog_data directly - this contains the actual software state used for register programming */ 6698 + struct dscl_prog_data *dscl_data = &pipe_ctx->plane_res.scl_data.dscl_prog_data; 6699 + 6700 + /* Recout (Rectangle of Interest) configuration - software state that programs RECOUT registers */ 6701 + state->dpp[i].recout_start_x = dscl_data->recout.x; 6702 + state->dpp[i].recout_start_y = dscl_data->recout.y; 6703 + state->dpp[i].recout_width = dscl_data->recout.width; 6704 + state->dpp[i].recout_height = dscl_data->recout.height; 6705 + 6706 + /* MPC (Multiple Pipe/Plane Combiner) size - software state that programs MPC_SIZE registers */ 6707 + state->dpp[i].mpc_width = dscl_data->mpc_size.width; 6708 + state->dpp[i].mpc_height = dscl_data->mpc_size.height; 6709 + 6710 + /* DSCL mode - software state that programs SCL_MODE registers */ 6711 + state->dpp[i].dscl_mode = dscl_data->dscl_mode; 6712 + 6713 + /* Scaler ratios - software state that programs scale ratio registers (use actual programmed ratios) */ 6714 + state->dpp[i].horz_ratio_int = dscl_data->ratios.h_scale_ratio >> 19; // Extract integer part from programmed ratio 6715 + state->dpp[i].vert_ratio_int = dscl_data->ratios.v_scale_ratio >> 19; // Extract integer part from programmed ratio 6716 + 6717 + /* Basic scaler taps - software state that programs tap control registers (use actual programmed taps) */ 6718 + state->dpp[i].h_taps = dscl_data->taps.h_taps + 1; // dscl_prog_data.taps stores (taps - 1), so add 1 back 6719 + state->dpp[i].v_taps = dscl_data->taps.v_taps + 1; // dscl_prog_data.taps stores (taps - 1), so add 1 back 6720 + } 6721 + } 6722 + 6723 + /* Capture essential clock state for underflow analysis */ 6724 + if (dc->clk_mgr && dc->clk_mgr->clks.dispclk_khz > 0) { 6725 + /* Core display clocks affecting bandwidth and timing */ 6726 + state->dccg.dispclk_khz = dc->clk_mgr->clks.dispclk_khz; 6727 + 6728 + /* Per-pipe clock configuration - only capture what's essential */ 6729 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6730 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6731 + if (pipe_ctx->stream) { 6732 + /* Essential clocks that directly affect underflow risk */ 6733 + state->dccg.dppclk_khz[i] = dc->clk_mgr->clks.dppclk_khz; 6734 + state->dccg.pixclk_khz[i] = pipe_ctx->stream->timing.pix_clk_100hz / 10; 6735 + state->dccg.dppclk_enable[i] = 1; 6736 + 6737 + /* DP stream clock only for DP signals */ 6738 + if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT || 6739 + pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { 6740 + state->dccg.dpstreamclk_enable[i] = 1; 6741 + } else { 6742 + state->dccg.dpstreamclk_enable[i] = 0; 6743 + } 6744 + } else { 6745 + /* Inactive pipe - no clocks */ 6746 + state->dccg.dppclk_khz[i] = 0; 6747 + state->dccg.pixclk_khz[i] = 0; 6748 + state->dccg.dppclk_enable[i] = 0; 6749 + if (i < 4) { 6750 + state->dccg.dpstreamclk_enable[i] = 0; 6751 + } 6752 + } 6753 + } 6754 + 6755 + /* DSC clock state - only when actually using DSC */ 6756 + for (i = 0; i < MAX_PIPES; i++) { 6757 + struct pipe_ctx *pipe_ctx = (i < dc->res_pool->pipe_count) ? &res_ctx->pipe_ctx[i] : NULL; 6758 + if (pipe_ctx && pipe_ctx->stream && pipe_ctx->stream->timing.dsc_cfg.num_slices_h > 0) { 6759 + state->dccg.dscclk_khz[i] = 400000; /* Typical DSC clock frequency */ 6760 + } else { 6761 + state->dccg.dscclk_khz[i] = 0; 6762 + } 6763 + } 6764 + 6765 + /* SYMCLK32 LE Control - only the essential HPO state for underflow analysis */ 6766 + for (i = 0; i < 2; i++) { 6767 + state->dccg.symclk32_le_enable[i] = 0; /* Default: disabled */ 6768 + } 6769 + 6770 + } 6771 + 6772 + /* Capture essential DSC configuration for underflow analysis */ 6773 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6774 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6775 + 6776 + if (pipe_ctx->stream && pipe_ctx->stream->timing.dsc_cfg.num_slices_h > 0) { 6777 + /* DSC is enabled - capture essential configuration */ 6778 + state->dsc[i].dsc_clock_enable = 1; 6779 + 6780 + /* DSC configuration affecting bandwidth and timing */ 6781 + struct dc_dsc_config *dsc_cfg = &pipe_ctx->stream->timing.dsc_cfg; 6782 + state->dsc[i].dsc_num_slices_h = dsc_cfg->num_slices_h; 6783 + state->dsc[i].dsc_num_slices_v = dsc_cfg->num_slices_v; 6784 + state->dsc[i].dsc_bits_per_pixel = dsc_cfg->bits_per_pixel; 6785 + 6786 + /* OPP pipe source for DSC forwarding */ 6787 + if (pipe_ctx->stream_res.opp) { 6788 + state->dsc[i].dscrm_dsc_forward_enable = 1; 6789 + state->dsc[i].dscrm_dsc_opp_pipe_source = pipe_ctx->stream_res.opp->inst; 6790 + } else { 6791 + state->dsc[i].dscrm_dsc_forward_enable = 0; 6792 + state->dsc[i].dscrm_dsc_opp_pipe_source = 0; 6793 + } 6794 + } else { 6795 + /* DSC not enabled - clear all fields */ 6796 + memset(&state->dsc[i], 0, sizeof(state->dsc[i])); 6797 + } 6798 + } 6799 + 6800 + /* Capture MPC programming state - comprehensive register field coverage */ 6801 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6802 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6803 + 6804 + if (pipe_ctx->plane_state && pipe_ctx->stream) { 6805 + struct dc_plane_state *plane_state = pipe_ctx->plane_state; 6806 + 6807 + /* MPCC blending tree and mode control - capture actual blend configuration */ 6808 + state->mpc.mpcc_mode[i] = (plane_state->blend_tf.type != TF_TYPE_BYPASS) ? 1 : 0; 6809 + state->mpc.mpcc_alpha_blend_mode[i] = plane_state->per_pixel_alpha ? 1 : 0; 6810 + state->mpc.mpcc_alpha_multiplied_mode[i] = plane_state->pre_multiplied_alpha ? 1 : 0; 6811 + state->mpc.mpcc_blnd_active_overlap_only[i] = 0; /* Default - no overlap restriction */ 6812 + state->mpc.mpcc_global_alpha[i] = plane_state->global_alpha_value; 6813 + state->mpc.mpcc_global_gain[i] = plane_state->global_alpha ? 255 : 0; 6814 + state->mpc.mpcc_bg_bpc[i] = 8; /* Standard 8-bit background */ 6815 + state->mpc.mpcc_bot_gain_mode[i] = 0; /* Standard gain mode */ 6816 + 6817 + /* MPCC blending tree connections - capture tree topology */ 6818 + if (pipe_ctx->bottom_pipe) { 6819 + state->mpc.mpcc_bot_sel[i] = pipe_ctx->bottom_pipe->pipe_idx; 6820 + } else { 6821 + state->mpc.mpcc_bot_sel[i] = 0xF; /* No bottom connection */ 6822 + } 6823 + state->mpc.mpcc_top_sel[i] = pipe_ctx->pipe_idx; /* This pipe's DPP ID */ 6824 + 6825 + /* MPCC output gamma control - capture gamma programming */ 6826 + if (plane_state->gamma_correction.type != GAMMA_CS_TFM_1D && plane_state->gamma_correction.num_entries > 0) { 6827 + state->mpc.mpcc_ogam_mode[i] = 1; /* Gamma enabled */ 6828 + state->mpc.mpcc_ogam_select[i] = 0; /* Bank A selection */ 6829 + state->mpc.mpcc_ogam_pwl_disable[i] = 0; /* PWL enabled */ 6830 + } else { 6831 + state->mpc.mpcc_ogam_mode[i] = 0; /* Bypass mode */ 6832 + state->mpc.mpcc_ogam_select[i] = 0; 6833 + state->mpc.mpcc_ogam_pwl_disable[i] = 1; /* PWL disabled */ 6834 + } 6835 + 6836 + /* MPCC pipe assignment and operational status */ 6837 + if (pipe_ctx->stream_res.opp) { 6838 + state->mpc.mpcc_opp_id[i] = pipe_ctx->stream_res.opp->inst; 6839 + } else { 6840 + state->mpc.mpcc_opp_id[i] = 0xF; /* No OPP assignment */ 6841 + } 6842 + 6843 + /* MPCC status indicators - active pipe state */ 6844 + state->mpc.mpcc_idle[i] = 0; /* Active pipe - not idle */ 6845 + state->mpc.mpcc_busy[i] = 1; /* Active pipe - busy processing */ 6846 + 6847 + } else { 6848 + /* Pipe not active - set disabled/idle state for all fields */ 6849 + state->mpc.mpcc_mode[i] = 0; 6850 + state->mpc.mpcc_alpha_blend_mode[i] = 0; 6851 + state->mpc.mpcc_alpha_multiplied_mode[i] = 0; 6852 + state->mpc.mpcc_blnd_active_overlap_only[i] = 0; 6853 + state->mpc.mpcc_global_alpha[i] = 0; 6854 + state->mpc.mpcc_global_gain[i] = 0; 6855 + state->mpc.mpcc_bg_bpc[i] = 0; 6856 + state->mpc.mpcc_bot_gain_mode[i] = 0; 6857 + state->mpc.mpcc_bot_sel[i] = 0xF; /* No bottom connection */ 6858 + state->mpc.mpcc_top_sel[i] = 0xF; /* No top connection */ 6859 + state->mpc.mpcc_ogam_mode[i] = 0; /* Bypass */ 6860 + state->mpc.mpcc_ogam_select[i] = 0; 6861 + state->mpc.mpcc_ogam_pwl_disable[i] = 1; /* PWL disabled */ 6862 + state->mpc.mpcc_opp_id[i] = 0xF; /* No OPP assignment */ 6863 + state->mpc.mpcc_idle[i] = 1; /* Idle */ 6864 + state->mpc.mpcc_busy[i] = 0; /* Not busy */ 6865 + } 6866 + } 6867 + 6868 + /* Capture OPP programming state for each pipe - comprehensive register field coverage */ 6869 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6870 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6871 + 6872 + if (!pipe_ctx->stream) 6873 + continue; 6874 + 6875 + if (pipe_ctx->stream_res.opp) { 6876 + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 6877 + 6878 + /* OPP Pipe Control */ 6879 + state->opp[i].opp_pipe_clock_enable = 1; /* Active pipe has clock enabled */ 6880 + 6881 + /* Display Pattern Generator (DPG) Control - 19 fields */ 6882 + if (pipe_ctx->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) { 6883 + state->opp[i].dpg_enable = 1; 6884 + } else { 6885 + /* Video mode - DPG disabled */ 6886 + state->opp[i].dpg_enable = 0; 6887 + } 6888 + 6889 + /* Format Control (FMT) - 18 fields */ 6890 + state->opp[i].fmt_pixel_encoding = timing->pixel_encoding; 6891 + 6892 + /* Chroma subsampling mode based on pixel encoding */ 6893 + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) { 6894 + state->opp[i].fmt_subsampling_mode = 1; /* 4:2:0 subsampling */ 6895 + } else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) { 6896 + state->opp[i].fmt_subsampling_mode = 2; /* 4:2:2 subsampling */ 6897 + } else { 6898 + state->opp[i].fmt_subsampling_mode = 0; /* No subsampling (4:4:4) */ 6899 + } 6900 + 6901 + state->opp[i].fmt_cbcr_bit_reduction_bypass = (timing->pixel_encoding == PIXEL_ENCODING_RGB) ? 1 : 0; 6902 + state->opp[i].fmt_stereosync_override = (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) ? 1 : 0; 6903 + 6904 + /* Dithering control based on bit depth */ 6905 + if (timing->display_color_depth < COLOR_DEPTH_121212) { 6906 + state->opp[i].fmt_spatial_dither_frame_counter_max = 15; /* Typical frame counter max */ 6907 + state->opp[i].fmt_spatial_dither_frame_counter_bit_swap = 0; /* No bit swapping */ 6908 + state->opp[i].fmt_spatial_dither_enable = 1; 6909 + state->opp[i].fmt_spatial_dither_mode = 0; /* Spatial dithering mode */ 6910 + state->opp[i].fmt_spatial_dither_depth = timing->display_color_depth; 6911 + state->opp[i].fmt_temporal_dither_enable = 0; /* Spatial dithering preferred */ 6912 + } else { 6913 + state->opp[i].fmt_spatial_dither_frame_counter_max = 0; 6914 + state->opp[i].fmt_spatial_dither_frame_counter_bit_swap = 0; 6915 + state->opp[i].fmt_spatial_dither_enable = 0; 6916 + state->opp[i].fmt_spatial_dither_mode = 0; 6917 + state->opp[i].fmt_spatial_dither_depth = 0; 6918 + state->opp[i].fmt_temporal_dither_enable = 0; 6919 + } 6920 + 6921 + /* Truncation control for bit depth reduction */ 6922 + if (timing->display_color_depth < COLOR_DEPTH_121212) { 6923 + state->opp[i].fmt_truncate_enable = 1; 6924 + state->opp[i].fmt_truncate_depth = timing->display_color_depth; 6925 + state->opp[i].fmt_truncate_mode = 0; /* Round mode */ 6926 + } else { 6927 + state->opp[i].fmt_truncate_enable = 0; 6928 + state->opp[i].fmt_truncate_depth = 0; 6929 + state->opp[i].fmt_truncate_mode = 0; 6930 + } 6931 + 6932 + /* Data clamping control */ 6933 + state->opp[i].fmt_clamp_data_enable = 1; /* Clamping typically enabled */ 6934 + state->opp[i].fmt_clamp_color_format = timing->pixel_encoding; 6935 + 6936 + /* Dynamic expansion for limited range content */ 6937 + if (timing->pixel_encoding != PIXEL_ENCODING_RGB) { 6938 + state->opp[i].fmt_dynamic_exp_enable = 1; /* YCbCr typically needs expansion */ 6939 + state->opp[i].fmt_dynamic_exp_mode = 0; /* Standard expansion */ 6940 + } else { 6941 + state->opp[i].fmt_dynamic_exp_enable = 0; /* RGB typically full range */ 6942 + state->opp[i].fmt_dynamic_exp_mode = 0; 6943 + } 6944 + 6945 + /* Legacy field for compatibility */ 6946 + state->opp[i].fmt_bit_depth_control = timing->display_color_depth; 6947 + 6948 + /* Output Buffer (OPPBUF) Control - 6 fields */ 6949 + state->opp[i].oppbuf_active_width = timing->h_addressable; 6950 + state->opp[i].oppbuf_pixel_repetition = 0; /* No pixel repetition by default */ 6951 + 6952 + /* Multi-Stream Output (MSO) / ODM segmentation */ 6953 + if (pipe_ctx->next_odm_pipe) { 6954 + state->opp[i].oppbuf_display_segmentation = 1; /* Segmented display */ 6955 + state->opp[i].oppbuf_overlap_pixel_num = 0; /* ODM overlap pixels */ 6956 + } else { 6957 + state->opp[i].oppbuf_display_segmentation = 0; /* Single segment */ 6958 + state->opp[i].oppbuf_overlap_pixel_num = 0; 6959 + } 6960 + 6961 + /* 3D/Stereo control */ 6962 + if (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) { 6963 + state->opp[i].oppbuf_3d_vact_space1_size = 30; /* Typical stereo blanking */ 6964 + state->opp[i].oppbuf_3d_vact_space2_size = 30; 6965 + } else { 6966 + state->opp[i].oppbuf_3d_vact_space1_size = 0; 6967 + state->opp[i].oppbuf_3d_vact_space2_size = 0; 6968 + } 6969 + 6970 + /* DSC Forward Config - 3 fields */ 6971 + if (timing->dsc_cfg.num_slices_h > 0) { 6972 + state->opp[i].dscrm_dsc_forward_enable = 1; 6973 + state->opp[i].dscrm_dsc_opp_pipe_source = pipe_ctx->stream_res.opp->inst; 6974 + state->opp[i].dscrm_dsc_forward_enable_status = 1; /* Status follows enable */ 6975 + } else { 6976 + state->opp[i].dscrm_dsc_forward_enable = 0; 6977 + state->opp[i].dscrm_dsc_opp_pipe_source = 0; 6978 + state->opp[i].dscrm_dsc_forward_enable_status = 0; 6979 + } 6980 + } else { 6981 + /* No OPP resource - set all fields to disabled state */ 6982 + memset(&state->opp[i], 0, sizeof(state->opp[i])); 6983 + } 6984 + } 6985 + 6986 + /* Capture OPTC programming state for each pipe - comprehensive register field coverage */ 6987 + for (i = 0; i < MAX_PIPES && i < dc->res_pool->pipe_count; i++) { 6988 + struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; 6989 + 6990 + if (!pipe_ctx->stream) 6991 + continue; 6992 + 6993 + if (pipe_ctx->stream_res.tg) { 6994 + struct dc_crtc_timing *timing = &pipe_ctx->stream->timing; 6995 + 6996 + state->optc[i].otg_master_inst = pipe_ctx->stream_res.tg->inst; 6997 + 6998 + /* OTG_CONTROL register - 5 fields */ 6999 + state->optc[i].otg_master_enable = 1; /* Active stream */ 7000 + state->optc[i].otg_disable_point_cntl = 0; /* Normal operation */ 7001 + state->optc[i].otg_start_point_cntl = 0; /* Normal start */ 7002 + state->optc[i].otg_field_number_cntl = (timing->flags.INTERLACE) ? 1 : 0; 7003 + state->optc[i].otg_out_mux = 0; /* Direct output */ 7004 + 7005 + /* OTG Horizontal Timing - 7 fields */ 7006 + state->optc[i].otg_h_total = timing->h_total; 7007 + state->optc[i].otg_h_blank_start = timing->h_addressable; 7008 + state->optc[i].otg_h_blank_end = timing->h_total - timing->h_front_porch; 7009 + state->optc[i].otg_h_sync_start = timing->h_addressable + timing->h_front_porch; 7010 + state->optc[i].otg_h_sync_end = timing->h_addressable + timing->h_front_porch + timing->h_sync_width; 7011 + state->optc[i].otg_h_sync_polarity = timing->flags.HSYNC_POSITIVE_POLARITY ? 0 : 1; 7012 + state->optc[i].otg_h_timing_div_mode = (pipe_ctx->next_odm_pipe) ? 1 : 0; /* ODM divide mode */ 7013 + 7014 + /* OTG Vertical Timing - 7 fields */ 7015 + state->optc[i].otg_v_total = timing->v_total; 7016 + state->optc[i].otg_v_blank_start = timing->v_addressable; 7017 + state->optc[i].otg_v_blank_end = timing->v_total - timing->v_front_porch; 7018 + state->optc[i].otg_v_sync_start = timing->v_addressable + timing->v_front_porch; 7019 + state->optc[i].otg_v_sync_end = timing->v_addressable + timing->v_front_porch + timing->v_sync_width; 7020 + state->optc[i].otg_v_sync_polarity = timing->flags.VSYNC_POSITIVE_POLARITY ? 0 : 1; 7021 + state->optc[i].otg_v_sync_mode = 0; /* Normal sync mode */ 7022 + 7023 + /* Initialize remaining core fields with appropriate defaults */ 7024 + // TODO: Update logic for accurate vtotal min/max 7025 + state->optc[i].otg_v_total_max = timing->v_total + 100; /* Typical DRR range */ 7026 + state->optc[i].otg_v_total_min = timing->v_total - 50; 7027 + state->optc[i].otg_v_total_mid = timing->v_total; 7028 + 7029 + /* ODM configuration */ 7030 + // TODO: Update logic to have complete ODM mappings (e.g. 3:1 and 4:1) stored in single pipe 7031 + if (pipe_ctx->next_odm_pipe) { 7032 + state->optc[i].optc_seg0_src_sel = pipe_ctx->stream_res.opp ? pipe_ctx->stream_res.opp->inst : 0; 7033 + state->optc[i].optc_seg1_src_sel = pipe_ctx->next_odm_pipe->stream_res.opp ? pipe_ctx->next_odm_pipe->stream_res.opp->inst : 0; 7034 + state->optc[i].optc_num_of_input_segment = 1; /* 2 segments - 1 */ 7035 + } else { 7036 + state->optc[i].optc_seg0_src_sel = pipe_ctx->stream_res.opp ? pipe_ctx->stream_res.opp->inst : 0; 7037 + state->optc[i].optc_seg1_src_sel = 0; 7038 + state->optc[i].optc_num_of_input_segment = 0; /* Single segment */ 7039 + } 7040 + 7041 + /* DSC configuration */ 7042 + if (timing->dsc_cfg.num_slices_h > 0) { 7043 + state->optc[i].optc_dsc_mode = 1; /* DSC enabled */ 7044 + state->optc[i].optc_dsc_bytes_per_pixel = timing->dsc_cfg.bits_per_pixel / 16; /* Convert to bytes */ 7045 + state->optc[i].optc_dsc_slice_width = timing->h_addressable / timing->dsc_cfg.num_slices_h; 7046 + } else { 7047 + state->optc[i].optc_dsc_mode = 0; 7048 + state->optc[i].optc_dsc_bytes_per_pixel = 0; 7049 + state->optc[i].optc_dsc_slice_width = 0; 7050 + } 7051 + 7052 + /* Essential control fields */ 7053 + state->optc[i].otg_stereo_enable = (timing->timing_3d_format != TIMING_3D_FORMAT_NONE) ? 1 : 0; 7054 + state->optc[i].otg_interlace_enable = timing->flags.INTERLACE ? 1 : 0; 7055 + state->optc[i].otg_clock_enable = 1; /* OTG clock enabled */ 7056 + state->optc[i].vtg0_enable = 1; /* VTG enabled for timing generation */ 7057 + 7058 + /* Initialize other key fields to defaults */ 7059 + state->optc[i].optc_input_pix_clk_en = 1; 7060 + state->optc[i].optc_segment_width = (pipe_ctx->next_odm_pipe) ? (timing->h_addressable / 2) : timing->h_addressable; 7061 + state->optc[i].otg_vready_offset = 1; 7062 + state->optc[i].otg_vstartup_start = timing->v_addressable + 10; 7063 + state->optc[i].otg_vupdate_offset = 0; 7064 + state->optc[i].otg_vupdate_width = 5; 7065 + } else { 7066 + /* No timing generator resource - initialize all fields to 0 */ 7067 + memset(&state->optc[i], 0, sizeof(state->optc[i])); 7068 + } 7069 + } 7070 + 7071 + state->state_valid = true; 7072 + return true; 6527 7073 } 6528 7074 6529 7075 void dc_log_preos_dmcub_info(const struct dc *dc)
+64 -40
drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
··· 265 265 black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED]; 266 266 break; 267 267 268 - /** 268 + /* 269 269 * Remove default and add case for all color space 270 270 * so when we forget to add new color space 271 271 * compiler will give a warning ··· 1293 1293 case HUBP_MEM_PROGRAM_VIEWPORT: 1294 1294 hwss_hubp_mem_program_viewport(params); 1295 1295 break; 1296 + case ABORT_CURSOR_OFFLOAD_UPDATE: 1297 + hwss_abort_cursor_offload_update(params); 1298 + break; 1296 1299 case SET_CURSOR_ATTRIBUTE: 1297 1300 hwss_set_cursor_attribute(params); 1298 1301 break; ··· 1321 1318 } 1322 1319 } 1323 1320 1324 - /** 1321 + /* 1325 1322 * Helper function to add OPTC pipe control lock to block sequence 1326 1323 */ 1327 1324 void hwss_add_optc_pipe_control_lock(struct block_sequence_state *seq_state, ··· 1338 1335 } 1339 1336 } 1340 1337 1341 - /** 1338 + /* 1342 1339 * Helper function to add HUBP set flip control GSL to block sequence 1343 1340 */ 1344 1341 void hwss_add_hubp_set_flip_control_gsl(struct block_sequence_state *seq_state, ··· 1353 1350 } 1354 1351 } 1355 1352 1356 - /** 1353 + /* 1357 1354 * Helper function to add HUBP program triplebuffer to block sequence 1358 1355 */ 1359 1356 void hwss_add_hubp_program_triplebuffer(struct block_sequence_state *seq_state, ··· 1370 1367 } 1371 1368 } 1372 1369 1373 - /** 1370 + /* 1374 1371 * Helper function to add HUBP update plane address to block sequence 1375 1372 */ 1376 1373 void hwss_add_hubp_update_plane_addr(struct block_sequence_state *seq_state, ··· 1385 1382 } 1386 1383 } 1387 1384 1388 - /** 1385 + /* 1389 1386 * Helper function to add DPP set input transfer function to block sequence 1390 1387 */ 1391 1388 void hwss_add_dpp_set_input_transfer_func(struct block_sequence_state *seq_state, ··· 1402 1399 } 1403 1400 } 1404 1401 1405 - /** 1402 + /* 1406 1403 * Helper function to add DPP program gamut remap to block sequence 1407 1404 */ 1408 1405 void hwss_add_dpp_program_gamut_remap(struct block_sequence_state *seq_state, ··· 1415 1412 } 1416 1413 } 1417 1414 1418 - /** 1415 + /* 1419 1416 * Helper function to add DPP program bias and scale to block sequence 1420 1417 */ 1421 1418 void hwss_add_dpp_program_bias_and_scale(struct block_sequence_state *seq_state, struct pipe_ctx *pipe_ctx) ··· 1427 1424 } 1428 1425 } 1429 1426 1430 - /** 1427 + /* 1431 1428 * Helper function to add OPTC program manual trigger to block sequence 1432 1429 */ 1433 1430 void hwss_add_optc_program_manual_trigger(struct block_sequence_state *seq_state, ··· 1440 1437 } 1441 1438 } 1442 1439 1443 - /** 1440 + /* 1444 1441 * Helper function to add DPP set output transfer function to block sequence 1445 1442 */ 1446 1443 void hwss_add_dpp_set_output_transfer_func(struct block_sequence_state *seq_state, ··· 1457 1454 } 1458 1455 } 1459 1456 1460 - /** 1457 + /* 1461 1458 * Helper function to add MPC update visual confirm to block sequence 1462 1459 */ 1463 1460 void hwss_add_mpc_update_visual_confirm(struct block_sequence_state *seq_state, ··· 1474 1471 } 1475 1472 } 1476 1473 1477 - /** 1474 + /* 1478 1475 * Helper function to add MPC power on MPC mem PWR to block sequence 1479 1476 */ 1480 1477 void hwss_add_mpc_power_on_mpc_mem_pwr(struct block_sequence_state *seq_state, ··· 1491 1488 } 1492 1489 } 1493 1490 1494 - /** 1491 + /* 1495 1492 * Helper function to add MPC set output CSC to block sequence 1496 1493 */ 1497 1494 void hwss_add_mpc_set_output_csc(struct block_sequence_state *seq_state, ··· 1510 1507 } 1511 1508 } 1512 1509 1513 - /** 1510 + /* 1514 1511 * Helper function to add MPC set OCSC default to block sequence 1515 1512 */ 1516 1513 void hwss_add_mpc_set_ocsc_default(struct block_sequence_state *seq_state, ··· 1529 1526 } 1530 1527 } 1531 1528 1532 - /** 1529 + /* 1533 1530 * Helper function to add DMUB send DMCUB command to block sequence 1534 1531 */ 1535 1532 void hwss_add_dmub_send_dmcub_cmd(struct block_sequence_state *seq_state, ··· 1546 1543 } 1547 1544 } 1548 1545 1549 - /** 1546 + /* 1550 1547 * Helper function to add DMUB SubVP save surface address to block sequence 1551 1548 */ 1552 1549 void hwss_add_dmub_subvp_save_surf_addr(struct block_sequence_state *seq_state, ··· 1563 1560 } 1564 1561 } 1565 1562 1566 - /** 1563 + /* 1567 1564 * Helper function to add HUBP wait for DCC meta propagation to block sequence 1568 1565 */ 1569 1566 void hwss_add_hubp_wait_for_dcc_meta_prop(struct block_sequence_state *seq_state, ··· 1578 1575 } 1579 1576 } 1580 1577 1581 - /** 1578 + /* 1582 1579 * Helper function to add HUBP wait pipe read start to block sequence 1583 1580 */ 1584 1581 void hwss_add_hubp_wait_pipe_read_start(struct block_sequence_state *seq_state, ··· 1591 1588 } 1592 1589 } 1593 1590 1594 - /** 1591 + /* 1595 1592 * Helper function to add HWS apply update flags for phantom to block sequence 1596 1593 */ 1597 1594 void hwss_add_hws_apply_update_flags_for_phantom(struct block_sequence_state *seq_state, ··· 1604 1601 } 1605 1602 } 1606 1603 1607 - /** 1604 + /* 1608 1605 * Helper function to add HWS update phantom VP position to block sequence 1609 1606 */ 1610 1607 void hwss_add_hws_update_phantom_vp_position(struct block_sequence_state *seq_state, ··· 1621 1618 } 1622 1619 } 1623 1620 1624 - /** 1621 + /* 1625 1622 * Helper function to add OPTC set ODM combine to block sequence 1626 1623 */ 1627 1624 void hwss_add_optc_set_odm_combine(struct block_sequence_state *seq_state, ··· 1639 1636 } 1640 1637 } 1641 1638 1642 - /** 1639 + /* 1643 1640 * Helper function to add OPTC set ODM bypass to block sequence 1644 1641 */ 1645 1642 void hwss_add_optc_set_odm_bypass(struct block_sequence_state *seq_state, ··· 1662 1659 dc_wake_and_execute_dmub_cmd(ctx, cmd, wait_type); 1663 1660 } 1664 1661 1665 - /** 1662 + /* 1666 1663 * Helper function to add TG program global sync to block sequence 1667 1664 */ 1668 1665 void hwss_add_tg_program_global_sync(struct block_sequence_state *seq_state, ··· 1685 1682 } 1686 1683 } 1687 1684 1688 - /** 1685 + /* 1689 1686 * Helper function to add TG wait for state to block sequence 1690 1687 */ 1691 1688 void hwss_add_tg_wait_for_state(struct block_sequence_state *seq_state, ··· 1700 1697 } 1701 1698 } 1702 1699 1703 - /** 1700 + /* 1704 1701 * Helper function to add TG set VTG params to block sequence 1705 1702 */ 1706 1703 void hwss_add_tg_set_vtg_params(struct block_sequence_state *seq_state, ··· 1717 1714 } 1718 1715 } 1719 1716 1720 - /** 1717 + /* 1721 1718 * Helper function to add TG setup vertical interrupt2 to block sequence 1722 1719 */ 1723 1720 void hwss_add_tg_setup_vertical_interrupt2(struct block_sequence_state *seq_state, ··· 1731 1728 } 1732 1729 } 1733 1730 1734 - /** 1731 + /* 1735 1732 * Helper function to add DPP set HDR multiplier to block sequence 1736 1733 */ 1737 1734 void hwss_add_dpp_set_hdr_multiplier(struct block_sequence_state *seq_state, ··· 1745 1742 } 1746 1743 } 1747 1744 1748 - /** 1745 + /* 1749 1746 * Helper function to add HUBP program DET size to block sequence 1750 1747 */ 1751 1748 void hwss_add_hubp_program_det_size(struct block_sequence_state *seq_state, ··· 1788 1785 } 1789 1786 } 1790 1787 1791 - /** 1788 + /* 1792 1789 * Helper function to add HUBP program DET segments to block sequence 1793 1790 */ 1794 1791 void hwss_add_hubp_program_det_segments(struct block_sequence_state *seq_state, ··· 1805 1802 } 1806 1803 } 1807 1804 1808 - /** 1805 + /* 1809 1806 * Helper function to add OPP set dynamic expansion to block sequence 1810 1807 */ 1811 1808 void hwss_add_opp_set_dyn_expansion(struct block_sequence_state *seq_state, ··· 1824 1821 } 1825 1822 } 1826 1823 1827 - /** 1824 + /* 1828 1825 * Helper function to add OPP program FMT to block sequence 1829 1826 */ 1830 1827 void hwss_add_opp_program_fmt(struct block_sequence_state *seq_state, ··· 1855 1852 } 1856 1853 } 1857 1854 1858 - /** 1855 + /* 1859 1856 * Helper function to add ABM set pipe to block sequence 1860 1857 */ 1861 1858 void hwss_add_abm_set_pipe(struct block_sequence_state *seq_state, ··· 1870 1867 } 1871 1868 } 1872 1869 1873 - /** 1870 + /* 1874 1871 * Helper function to add ABM set level to block sequence 1875 1872 */ 1876 1873 void hwss_add_abm_set_level(struct block_sequence_state *seq_state, ··· 1885 1882 } 1886 1883 } 1887 1884 1888 - /** 1885 + /* 1889 1886 * Helper function to add TG enable CRTC to block sequence 1890 1887 */ 1891 1888 void hwss_add_tg_enable_crtc(struct block_sequence_state *seq_state, ··· 1898 1895 } 1899 1896 } 1900 1897 1901 - /** 1898 + /* 1902 1899 * Helper function to add HUBP wait flip pending to block sequence 1903 1900 */ 1904 1901 void hwss_add_hubp_wait_flip_pending(struct block_sequence_state *seq_state, ··· 1915 1912 } 1916 1913 } 1917 1914 1918 - /** 1915 + /* 1919 1916 * Helper function to add TG wait double buffer pending to block sequence 1920 1917 */ 1921 1918 void hwss_add_tg_wait_double_buffer_pending(struct block_sequence_state *seq_state, ··· 3079 3076 hubp->funcs->mem_program_viewport(hubp, viewport, viewport_c); 3080 3077 } 3081 3078 3079 + void hwss_abort_cursor_offload_update(union block_sequence_params *params) 3080 + { 3081 + struct dc *dc = params->abort_cursor_offload_update_params.dc; 3082 + struct pipe_ctx *pipe_ctx = params->abort_cursor_offload_update_params.pipe_ctx; 3083 + 3084 + if (dc && dc->hwss.abort_cursor_offload_update) 3085 + dc->hwss.abort_cursor_offload_update(dc, pipe_ctx); 3086 + } 3087 + 3082 3088 void hwss_set_cursor_attribute(union block_sequence_params *params) 3083 3089 { 3084 3090 struct dc *dc = params->set_cursor_attribute_params.dc; ··· 3282 3270 } 3283 3271 } 3284 3272 3285 - /** 3273 + /* 3286 3274 * Helper function to add MPC update blending to block sequence 3287 3275 */ 3288 3276 void hwss_add_mpc_update_blending(struct block_sequence_state *seq_state, ··· 3299 3287 } 3300 3288 } 3301 3289 3302 - /** 3290 + /* 3303 3291 * Helper function to add MPC insert plane to block sequence 3304 3292 */ 3305 3293 void hwss_add_mpc_insert_plane(struct block_sequence_state *seq_state, ··· 3324 3312 } 3325 3313 } 3326 3314 3327 - /** 3315 + /* 3328 3316 * Helper function to add MPC assert idle MPCC to block sequence 3329 3317 */ 3330 3318 void hwss_add_mpc_assert_idle_mpcc(struct block_sequence_state *seq_state, ··· 3339 3327 } 3340 3328 } 3341 3329 3342 - /** 3330 + /* 3343 3331 * Helper function to add HUBP set blank to block sequence 3344 3332 */ 3345 3333 void hwss_add_hubp_set_blank(struct block_sequence_state *seq_state, ··· 3942 3930 seq_state->steps[*seq_state->num_steps].params.hubp_mem_program_viewport_params.hubp = hubp; 3943 3931 seq_state->steps[*seq_state->num_steps].params.hubp_mem_program_viewport_params.viewport = viewport; 3944 3932 seq_state->steps[*seq_state->num_steps].params.hubp_mem_program_viewport_params.viewport_c = viewport_c; 3933 + (*seq_state->num_steps)++; 3934 + } 3935 + } 3936 + 3937 + void hwss_add_abort_cursor_offload_update(struct block_sequence_state *seq_state, 3938 + struct dc *dc, 3939 + struct pipe_ctx *pipe_ctx) 3940 + { 3941 + if (*seq_state->num_steps < MAX_HWSS_BLOCK_SEQUENCE_SIZE) { 3942 + seq_state->steps[*seq_state->num_steps].func = ABORT_CURSOR_OFFLOAD_UPDATE; 3943 + seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params.dc = dc; 3944 + seq_state->steps[*seq_state->num_steps].params.abort_cursor_offload_update_params.pipe_ctx = pipe_ctx; 3945 3945 (*seq_state->num_steps)++; 3946 3946 } 3947 3947 }
+70 -6
drivers/gpu/drm/amd/display/dc/core/dc_resource.c
··· 99 99 100 100 #define UNABLE_TO_SPLIT -1 101 101 102 + static void capture_pipe_topology_data(struct dc *dc, int plane_idx, int slice_idx, int stream_idx, 103 + int dpp_inst, int opp_inst, int tg_inst, bool is_phantom_pipe) 104 + { 105 + struct pipe_topology_snapshot *current_snapshot = &dc->debug_data.topology_history.snapshots[dc->debug_data.topology_history.current_snapshot_index]; 106 + 107 + if (current_snapshot->line_count >= MAX_PIPES) 108 + return; 109 + 110 + current_snapshot->pipe_log_lines[current_snapshot->line_count].is_phantom_pipe = is_phantom_pipe; 111 + current_snapshot->pipe_log_lines[current_snapshot->line_count].plane_idx = plane_idx; 112 + current_snapshot->pipe_log_lines[current_snapshot->line_count].slice_idx = slice_idx; 113 + current_snapshot->pipe_log_lines[current_snapshot->line_count].stream_idx = stream_idx; 114 + current_snapshot->pipe_log_lines[current_snapshot->line_count].dpp_inst = dpp_inst; 115 + current_snapshot->pipe_log_lines[current_snapshot->line_count].opp_inst = opp_inst; 116 + current_snapshot->pipe_log_lines[current_snapshot->line_count].tg_inst = tg_inst; 117 + 118 + current_snapshot->line_count++; 119 + } 120 + 121 + static void start_new_topology_snapshot(struct dc *dc, struct dc_state *state) 122 + { 123 + // Move to next snapshot slot (circular buffer) 124 + dc->debug_data.topology_history.current_snapshot_index = (dc->debug_data.topology_history.current_snapshot_index + 1) % MAX_TOPOLOGY_SNAPSHOTS; 125 + 126 + // Clear the new snapshot 127 + struct pipe_topology_snapshot *current_snapshot = &dc->debug_data.topology_history.snapshots[dc->debug_data.topology_history.current_snapshot_index]; 128 + memset(current_snapshot, 0, sizeof(*current_snapshot)); 129 + 130 + // Set metadata 131 + current_snapshot->timestamp_us = dm_get_timestamp(dc->ctx); 132 + current_snapshot->stream_count = state->stream_count; 133 + current_snapshot->phantom_stream_count = state->phantom_stream_count; 134 + } 135 + 102 136 enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) 103 137 { 104 138 enum dce_version dc_version = DCE_VERSION_UNKNOWN; ··· 2345 2311 2346 2312 static void resource_log_pipe(struct dc *dc, struct pipe_ctx *pipe, 2347 2313 int stream_idx, int slice_idx, int plane_idx, int slice_count, 2348 - bool is_primary) 2314 + bool is_primary, bool is_phantom_pipe) 2349 2315 { 2350 2316 DC_LOGGER_INIT(dc->ctx->logger); 2351 2317 2318 + // new format for logging: bit storing code 2352 2319 if (slice_idx == 0 && plane_idx == 0 && is_primary) { 2353 2320 /* case 0 (OTG master pipe with plane) */ 2354 2321 DC_LOG_DC(" | plane%d slice%d stream%d|", ··· 2358 2323 pipe->plane_res.dpp->inst, 2359 2324 pipe->stream_res.opp->inst, 2360 2325 pipe->stream_res.tg->inst); 2326 + capture_pipe_topology_data(dc, plane_idx, slice_idx, stream_idx, 2327 + pipe->plane_res.dpp->inst, 2328 + pipe->stream_res.opp->inst, 2329 + pipe->stream_res.tg->inst, is_phantom_pipe); 2361 2330 } else if (slice_idx == 0 && plane_idx == -1) { 2362 2331 /* case 1 (OTG master pipe without plane) */ 2363 2332 DC_LOG_DC(" | slice%d stream%d|", ··· 2370 2331 pipe->stream_res.opp->inst, 2371 2332 pipe->stream_res.opp->inst, 2372 2333 pipe->stream_res.tg->inst); 2334 + capture_pipe_topology_data(dc, 0xF, slice_idx, stream_idx, 2335 + pipe->plane_res.dpp->inst, 2336 + pipe->stream_res.opp->inst, 2337 + pipe->stream_res.tg->inst, is_phantom_pipe); 2373 2338 } else if (slice_idx != 0 && plane_idx == 0 && is_primary) { 2374 2339 /* case 2 (OPP head pipe with plane) */ 2375 2340 DC_LOG_DC(" | plane%d slice%d | |", ··· 2381 2338 DC_LOG_DC(" |DPP%d----OPP%d----| |", 2382 2339 pipe->plane_res.dpp->inst, 2383 2340 pipe->stream_res.opp->inst); 2341 + capture_pipe_topology_data(dc, plane_idx, slice_idx, stream_idx, 2342 + pipe->plane_res.dpp->inst, 2343 + pipe->stream_res.opp->inst, 2344 + pipe->stream_res.tg->inst, is_phantom_pipe); 2384 2345 } else if (slice_idx != 0 && plane_idx == -1) { 2385 2346 /* case 3 (OPP head pipe without plane) */ 2386 2347 DC_LOG_DC(" | slice%d | |", slice_idx); 2387 2348 DC_LOG_DC(" |DPG%d----OPP%d----| |", 2388 2349 pipe->plane_res.dpp->inst, 2389 2350 pipe->stream_res.opp->inst); 2351 + capture_pipe_topology_data(dc, 0xF, slice_idx, stream_idx, 2352 + pipe->plane_res.dpp->inst, 2353 + pipe->stream_res.opp->inst, 2354 + pipe->stream_res.tg->inst, is_phantom_pipe); 2390 2355 } else if (slice_idx == slice_count - 1) { 2391 2356 /* case 4 (DPP pipe in last slice) */ 2392 2357 DC_LOG_DC(" | plane%d | |", plane_idx); 2393 2358 DC_LOG_DC(" |DPP%d----| |", 2394 2359 pipe->plane_res.dpp->inst); 2360 + capture_pipe_topology_data(dc, plane_idx, slice_idx, stream_idx, 2361 + pipe->plane_res.dpp->inst, 2362 + pipe->stream_res.opp->inst, 2363 + pipe->stream_res.tg->inst, is_phantom_pipe); 2395 2364 } else { 2396 2365 /* case 5 (DPP pipe not in last slice) */ 2397 2366 DC_LOG_DC(" | plane%d | | |", plane_idx); 2398 2367 DC_LOG_DC(" |DPP%d----| | |", 2399 2368 pipe->plane_res.dpp->inst); 2369 + capture_pipe_topology_data(dc, plane_idx, slice_idx, stream_idx, 2370 + pipe->plane_res.dpp->inst, 2371 + pipe->stream_res.opp->inst, 2372 + pipe->stream_res.tg->inst, is_phantom_pipe); 2400 2373 } 2401 2374 } 2402 2375 2403 2376 static void resource_log_pipe_for_stream(struct dc *dc, struct dc_state *state, 2404 - struct pipe_ctx *otg_master, int stream_idx) 2377 + struct pipe_ctx *otg_master, int stream_idx, bool is_phantom_pipe) 2405 2378 { 2406 2379 struct pipe_ctx *opp_heads[MAX_PIPES]; 2407 2380 struct pipe_ctx *dpp_pipes[MAX_PIPES]; ··· 2443 2384 resource_log_pipe(dc, dpp_pipes[dpp_idx], 2444 2385 stream_idx, slice_idx, 2445 2386 plane_idx, slice_count, 2446 - is_primary); 2387 + is_primary, is_phantom_pipe); 2447 2388 } 2448 2389 } else { 2449 2390 resource_log_pipe(dc, opp_heads[slice_idx], 2450 2391 stream_idx, slice_idx, plane_idx, 2451 - slice_count, true); 2392 + slice_count, true, is_phantom_pipe); 2452 2393 } 2453 2394 2454 2395 } ··· 2479 2420 struct pipe_ctx *otg_master; 2480 2421 int stream_idx, phantom_stream_idx; 2481 2422 DC_LOGGER_INIT(dc->ctx->logger); 2423 + bool is_phantom_pipe = false; 2424 + 2425 + // Start a new snapshot for this topology update 2426 + start_new_topology_snapshot(dc, state); 2482 2427 2483 2428 DC_LOG_DC(" pipe topology update"); 2484 2429 DC_LOG_DC(" ________________________"); ··· 2496 2433 if (!otg_master) 2497 2434 continue; 2498 2435 2499 - resource_log_pipe_for_stream(dc, state, otg_master, stream_idx); 2436 + resource_log_pipe_for_stream(dc, state, otg_master, stream_idx, is_phantom_pipe); 2500 2437 } 2501 2438 if (state->phantom_stream_count > 0) { 2439 + is_phantom_pipe = true; 2502 2440 DC_LOG_DC(" | (phantom pipes) |"); 2503 2441 for (stream_idx = 0; stream_idx < state->stream_count; stream_idx++) { 2504 2442 if (state->stream_status[stream_idx].mall_stream_config.type != SUBVP_MAIN) ··· 2512 2448 if (!otg_master) 2513 2449 continue; 2514 2450 2515 - resource_log_pipe_for_stream(dc, state, otg_master, stream_idx); 2451 + resource_log_pipe_for_stream(dc, state, otg_master, stream_idx, is_phantom_pipe); 2516 2452 } 2517 2453 } 2518 2454 DC_LOG_DC(" |________________________|\n");
+8 -3
drivers/gpu/drm/amd/display/dc/core/dc_stream.c
··· 737 737 { 738 738 uint8_t i; 739 739 bool ret = false; 740 - struct dc *dc = stream->ctx->dc; 741 - struct resource_context *res_ctx = 742 - &dc->current_state->res_ctx; 740 + struct dc *dc; 741 + struct resource_context *res_ctx; 742 + 743 + if (!stream->ctx) 744 + return false; 745 + 746 + dc = stream->ctx->dc; 747 + res_ctx = &dc->current_state->res_ctx; 743 748 744 749 dc_exit_ips_for_hw_access(dc); 745 750
+489 -1
drivers/gpu/drm/amd/display/dc/dc.h
··· 63 63 struct dcn_optc_reg_state; 64 64 struct dcn_dccg_reg_state; 65 65 66 - #define DC_VER "3.2.358" 66 + #define DC_VER "3.2.359" 67 67 68 68 /** 69 69 * MAX_SURFACES - representative of the upper bound of surfaces that can be piped to a single CRTC ··· 899 899 uint32_t ltFailCount; 900 900 uint32_t i2cErrorCount; 901 901 uint32_t auxErrorCount; 902 + struct pipe_topology_history topology_history; 902 903 }; 903 904 904 905 struct dc_phy_addr_space_config { ··· 2792 2791 void dc_get_underflow_debug_data_for_otg(struct dc *dc, int primary_otg_inst, struct dc_underflow_debug_data *out_data); 2793 2792 2794 2793 void dc_get_power_feature_status(struct dc *dc, int primary_otg_inst, struct power_features *out_data); 2794 + 2795 + /** 2796 + * Software state variables used to program register fields across the display pipeline 2797 + */ 2798 + struct dc_register_software_state { 2799 + /* HUBP register programming variables for each pipe */ 2800 + struct { 2801 + bool valid_plane_state; 2802 + bool valid_stream; 2803 + bool min_dc_gfx_version9; 2804 + uint32_t vtg_sel; /* DCHUBP_CNTL->HUBP_VTG_SEL from pipe_ctx->stream_res.tg->inst */ 2805 + uint32_t hubp_clock_enable; /* HUBP_CLK_CNTL->HUBP_CLOCK_ENABLE from power management */ 2806 + uint32_t surface_pixel_format; /* DCSURF_SURFACE_CONFIG->SURFACE_PIXEL_FORMAT from plane_state->format */ 2807 + uint32_t rotation_angle; /* DCSURF_SURFACE_CONFIG->ROTATION_ANGLE from plane_state->rotation */ 2808 + uint32_t h_mirror_en; /* DCSURF_SURFACE_CONFIG->H_MIRROR_EN from plane_state->horizontal_mirror */ 2809 + uint32_t surface_dcc_en; /* DCSURF_SURFACE_CONTROL->PRIMARY_SURFACE_DCC_EN from dcc->enable */ 2810 + uint32_t surface_size_width; /* HUBP_SIZE->SURFACE_SIZE_WIDTH from plane_size.surface_size.width */ 2811 + uint32_t surface_size_height; /* HUBP_SIZE->SURFACE_SIZE_HEIGHT from plane_size.surface_size.height */ 2812 + uint32_t pri_viewport_width; /* DCSURF_PRI_VIEWPORT_DIMENSION->PRI_VIEWPORT_WIDTH from scaler_data.viewport.width */ 2813 + uint32_t pri_viewport_height; /* DCSURF_PRI_VIEWPORT_DIMENSION->PRI_VIEWPORT_HEIGHT from scaler_data.viewport.height */ 2814 + uint32_t pri_viewport_x_start; /* DCSURF_PRI_VIEWPORT_START->PRI_VIEWPORT_X_START from scaler_data.viewport.x */ 2815 + uint32_t pri_viewport_y_start; /* DCSURF_PRI_VIEWPORT_START->PRI_VIEWPORT_Y_START from scaler_data.viewport.y */ 2816 + uint32_t cursor_enable; /* CURSOR_CONTROL->CURSOR_ENABLE from cursor_attributes.enable */ 2817 + uint32_t cursor_width; /* CURSOR_SETTINGS->CURSOR_WIDTH from cursor_position.width */ 2818 + uint32_t cursor_height; /* CURSOR_SETTINGS->CURSOR_HEIGHT from cursor_position.height */ 2819 + 2820 + /* Additional DCC configuration */ 2821 + uint32_t surface_dcc_ind_64b_blk; /* DCSURF_SURFACE_CONTROL->PRIMARY_SURFACE_DCC_IND_64B_BLK from dcc.independent_64b_blks */ 2822 + uint32_t surface_dcc_ind_128b_blk; /* DCSURF_SURFACE_CONTROL->PRIMARY_SURFACE_DCC_IND_128B_BLK from dcc.independent_128b_blks */ 2823 + 2824 + /* Surface pitch configuration */ 2825 + uint32_t surface_pitch; /* DCSURF_SURFACE_PITCH->PITCH from plane_size.surface_pitch */ 2826 + uint32_t meta_pitch; /* DCSURF_SURFACE_PITCH->META_PITCH from dcc.meta_pitch */ 2827 + uint32_t chroma_pitch; /* DCSURF_SURFACE_PITCH_C->PITCH_C from plane_size.chroma_pitch */ 2828 + uint32_t meta_pitch_c; /* DCSURF_SURFACE_PITCH_C->META_PITCH_C from dcc.meta_pitch_c */ 2829 + 2830 + /* Surface addresses */ 2831 + uint32_t primary_surface_address_low; /* DCSURF_PRIMARY_SURFACE_ADDRESS->PRIMARY_SURFACE_ADDRESS from address.grph.addr.low_part */ 2832 + uint32_t primary_surface_address_high; /* DCSURF_PRIMARY_SURFACE_ADDRESS_HIGH->PRIMARY_SURFACE_ADDRESS_HIGH from address.grph.addr.high_part */ 2833 + uint32_t primary_meta_surface_address_low; /* DCSURF_PRIMARY_META_SURFACE_ADDRESS->PRIMARY_META_SURFACE_ADDRESS from address.grph.meta_addr.low_part */ 2834 + uint32_t primary_meta_surface_address_high; /* DCSURF_PRIMARY_META_SURFACE_ADDRESS_HIGH->PRIMARY_META_SURFACE_ADDRESS_HIGH from address.grph.meta_addr.high_part */ 2835 + 2836 + /* TMZ configuration */ 2837 + uint32_t primary_surface_tmz; /* DCSURF_SURFACE_CONTROL->PRIMARY_SURFACE_TMZ from address.tmz_surface */ 2838 + uint32_t primary_meta_surface_tmz; /* DCSURF_SURFACE_CONTROL->PRIMARY_META_SURFACE_TMZ from address.tmz_surface */ 2839 + 2840 + /* Tiling configuration */ 2841 + uint32_t sw_mode; /* DCSURF_TILING_CONFIG->SW_MODE from tiling_info.gfx9.swizzle */ 2842 + uint32_t num_pipes; /* DCSURF_ADDR_CONFIG->NUM_PIPES from tiling_info.gfx9.num_pipes */ 2843 + uint32_t num_banks; /* DCSURF_ADDR_CONFIG->NUM_BANKS from tiling_info.gfx9.num_banks */ 2844 + uint32_t pipe_interleave; /* DCSURF_ADDR_CONFIG->PIPE_INTERLEAVE from tiling_info.gfx9.pipe_interleave */ 2845 + uint32_t num_shader_engines; /* DCSURF_ADDR_CONFIG->NUM_SE from tiling_info.gfx9.num_shader_engines */ 2846 + uint32_t num_rb_per_se; /* DCSURF_ADDR_CONFIG->NUM_RB_PER_SE from tiling_info.gfx9.num_rb_per_se */ 2847 + uint32_t num_pkrs; /* DCSURF_ADDR_CONFIG->NUM_PKRS from tiling_info.gfx9.num_pkrs */ 2848 + 2849 + /* DML Request Size Configuration - Luma */ 2850 + uint32_t rq_chunk_size; /* DCHUBP_REQ_SIZE_CONFIG->CHUNK_SIZE from rq_regs.rq_regs_l.chunk_size */ 2851 + uint32_t rq_min_chunk_size; /* DCHUBP_REQ_SIZE_CONFIG->MIN_CHUNK_SIZE from rq_regs.rq_regs_l.min_chunk_size */ 2852 + uint32_t rq_meta_chunk_size; /* DCHUBP_REQ_SIZE_CONFIG->META_CHUNK_SIZE from rq_regs.rq_regs_l.meta_chunk_size */ 2853 + uint32_t rq_min_meta_chunk_size; /* DCHUBP_REQ_SIZE_CONFIG->MIN_META_CHUNK_SIZE from rq_regs.rq_regs_l.min_meta_chunk_size */ 2854 + uint32_t rq_dpte_group_size; /* DCHUBP_REQ_SIZE_CONFIG->DPTE_GROUP_SIZE from rq_regs.rq_regs_l.dpte_group_size */ 2855 + uint32_t rq_mpte_group_size; /* DCHUBP_REQ_SIZE_CONFIG->MPTE_GROUP_SIZE from rq_regs.rq_regs_l.mpte_group_size */ 2856 + uint32_t rq_swath_height_l; /* DCHUBP_REQ_SIZE_CONFIG->SWATH_HEIGHT_L from rq_regs.rq_regs_l.swath_height */ 2857 + uint32_t rq_pte_row_height_l; /* DCHUBP_REQ_SIZE_CONFIG->PTE_ROW_HEIGHT_L from rq_regs.rq_regs_l.pte_row_height */ 2858 + 2859 + /* DML Request Size Configuration - Chroma */ 2860 + uint32_t rq_chunk_size_c; /* DCHUBP_REQ_SIZE_CONFIG_C->CHUNK_SIZE_C from rq_regs.rq_regs_c.chunk_size */ 2861 + uint32_t rq_min_chunk_size_c; /* DCHUBP_REQ_SIZE_CONFIG_C->MIN_CHUNK_SIZE_C from rq_regs.rq_regs_c.min_chunk_size */ 2862 + uint32_t rq_meta_chunk_size_c; /* DCHUBP_REQ_SIZE_CONFIG_C->META_CHUNK_SIZE_C from rq_regs.rq_regs_c.meta_chunk_size */ 2863 + uint32_t rq_min_meta_chunk_size_c; /* DCHUBP_REQ_SIZE_CONFIG_C->MIN_META_CHUNK_SIZE_C from rq_regs.rq_regs_c.min_meta_chunk_size */ 2864 + uint32_t rq_dpte_group_size_c; /* DCHUBP_REQ_SIZE_CONFIG_C->DPTE_GROUP_SIZE_C from rq_regs.rq_regs_c.dpte_group_size */ 2865 + uint32_t rq_mpte_group_size_c; /* DCHUBP_REQ_SIZE_CONFIG_C->MPTE_GROUP_SIZE_C from rq_regs.rq_regs_c.mpte_group_size */ 2866 + uint32_t rq_swath_height_c; /* DCHUBP_REQ_SIZE_CONFIG_C->SWATH_HEIGHT_C from rq_regs.rq_regs_c.swath_height */ 2867 + uint32_t rq_pte_row_height_c; /* DCHUBP_REQ_SIZE_CONFIG_C->PTE_ROW_HEIGHT_C from rq_regs.rq_regs_c.pte_row_height */ 2868 + 2869 + /* DML Expansion Modes */ 2870 + uint32_t drq_expansion_mode; /* DCN_EXPANSION_MODE->DRQ_EXPANSION_MODE from rq_regs.drq_expansion_mode */ 2871 + uint32_t prq_expansion_mode; /* DCN_EXPANSION_MODE->PRQ_EXPANSION_MODE from rq_regs.prq_expansion_mode */ 2872 + uint32_t mrq_expansion_mode; /* DCN_EXPANSION_MODE->MRQ_EXPANSION_MODE from rq_regs.mrq_expansion_mode */ 2873 + uint32_t crq_expansion_mode; /* DCN_EXPANSION_MODE->CRQ_EXPANSION_MODE from rq_regs.crq_expansion_mode */ 2874 + 2875 + /* DML DLG parameters - nominal */ 2876 + uint32_t dst_y_per_vm_vblank; /* NOM_PARAMETERS_0->DST_Y_PER_VM_VBLANK from dlg_regs.dst_y_per_vm_vblank */ 2877 + uint32_t dst_y_per_row_vblank; /* NOM_PARAMETERS_0->DST_Y_PER_ROW_VBLANK from dlg_regs.dst_y_per_row_vblank */ 2878 + uint32_t dst_y_per_vm_flip; /* NOM_PARAMETERS_1->DST_Y_PER_VM_FLIP from dlg_regs.dst_y_per_vm_flip */ 2879 + uint32_t dst_y_per_row_flip; /* NOM_PARAMETERS_1->DST_Y_PER_ROW_FLIP from dlg_regs.dst_y_per_row_flip */ 2880 + 2881 + /* DML prefetch settings */ 2882 + uint32_t dst_y_prefetch; /* PREFETCH_SETTINS->DST_Y_PREFETCH from dlg_regs.dst_y_prefetch */ 2883 + uint32_t vratio_prefetch; /* PREFETCH_SETTINS->VRATIO_PREFETCH from dlg_regs.vratio_prefetch */ 2884 + uint32_t vratio_prefetch_c; /* PREFETCH_SETTINS_C->VRATIO_PREFETCH_C from dlg_regs.vratio_prefetch_c */ 2885 + 2886 + /* TTU parameters */ 2887 + uint32_t qos_level_low_wm; /* TTU_CNTL1->QoSLevelLowWaterMark from ttu_regs.qos_level_low_wm */ 2888 + uint32_t qos_level_high_wm; /* TTU_CNTL1->QoSLevelHighWaterMark from ttu_regs.qos_level_high_wm */ 2889 + uint32_t qos_level_flip; /* TTU_CNTL2->QoS_LEVEL_FLIP_L from ttu_regs.qos_level_flip */ 2890 + uint32_t min_ttu_vblank; /* DCN_GLOBAL_TTU_CNTL->MIN_TTU_VBLANK from ttu_regs.min_ttu_vblank */ 2891 + } hubp[MAX_PIPES]; 2892 + 2893 + /* HUBBUB register programming variables */ 2894 + struct { 2895 + /* Individual DET buffer control per pipe - software state that programs DET registers */ 2896 + uint32_t det0_size; /* DCHUBBUB_DET0_CTRL->DET0_SIZE from hubbub->funcs->program_det_size(hubbub, 0, det_buffer_size_kb) */ 2897 + uint32_t det1_size; /* DCHUBBUB_DET1_CTRL->DET1_SIZE from hubbub->funcs->program_det_size(hubbub, 1, det_buffer_size_kb) */ 2898 + uint32_t det2_size; /* DCHUBBUB_DET2_CTRL->DET2_SIZE from hubbub->funcs->program_det_size(hubbub, 2, det_buffer_size_kb) */ 2899 + uint32_t det3_size; /* DCHUBBUB_DET3_CTRL->DET3_SIZE from hubbub->funcs->program_det_size(hubbub, 3, det_buffer_size_kb) */ 2900 + 2901 + /* Compression buffer control - software state that programs COMPBUF registers */ 2902 + uint32_t compbuf_size; /* DCHUBBUB_COMPBUF_CTRL->COMPBUF_SIZE from hubbub->funcs->program_compbuf_size(hubbub, compbuf_size_kb, safe_to_increase) */ 2903 + uint32_t compbuf_reserved_space_64b; /* COMPBUF_RESERVED_SPACE->COMPBUF_RESERVED_SPACE_64B from hubbub2->pixel_chunk_size / 32 */ 2904 + uint32_t compbuf_reserved_space_zs; /* COMPBUF_RESERVED_SPACE->COMPBUF_RESERVED_SPACE_ZS from hubbub2->pixel_chunk_size / 128 */ 2905 + } hubbub; 2906 + 2907 + /* DPP register programming variables for each pipe (simplified for available fields) */ 2908 + struct { 2909 + uint32_t dpp_clock_enable; /* DPP_CONTROL->DPP_CLOCK_ENABLE from dppclk_enable */ 2910 + 2911 + /* Recout (Rectangle of Interest) configuration */ 2912 + uint32_t recout_start_x; /* RECOUT_START->RECOUT_START_X from pipe_ctx->plane_res.scl_data.recout.x */ 2913 + uint32_t recout_start_y; /* RECOUT_START->RECOUT_START_Y from pipe_ctx->plane_res.scl_data.recout.y */ 2914 + uint32_t recout_width; /* RECOUT_SIZE->RECOUT_WIDTH from pipe_ctx->plane_res.scl_data.recout.width */ 2915 + uint32_t recout_height; /* RECOUT_SIZE->RECOUT_HEIGHT from pipe_ctx->plane_res.scl_data.recout.height */ 2916 + 2917 + /* MPC (Multiple Pipe/Plane Combiner) size configuration */ 2918 + uint32_t mpc_width; /* MPC_SIZE->MPC_WIDTH from pipe_ctx->plane_res.scl_data.h_active */ 2919 + uint32_t mpc_height; /* MPC_SIZE->MPC_HEIGHT from pipe_ctx->plane_res.scl_data.v_active */ 2920 + 2921 + /* DSCL mode configuration */ 2922 + uint32_t dscl_mode; /* SCL_MODE->DSCL_MODE from pipe_ctx->plane_res.scl_data.dscl_prog_data.dscl_mode */ 2923 + 2924 + /* Scaler ratios (simplified to integer parts) */ 2925 + uint32_t horz_ratio_int; /* SCL_HORZ_FILTER_SCALE_RATIO->SCL_H_SCALE_RATIO integer part from ratios.horz */ 2926 + uint32_t vert_ratio_int; /* SCL_VERT_FILTER_SCALE_RATIO->SCL_V_SCALE_RATIO integer part from ratios.vert */ 2927 + 2928 + /* Basic scaler taps */ 2929 + uint32_t h_taps; /* SCL_TAP_CONTROL->SCL_H_NUM_TAPS from taps.h_taps */ 2930 + uint32_t v_taps; /* SCL_TAP_CONTROL->SCL_V_NUM_TAPS from taps.v_taps */ 2931 + } dpp[MAX_PIPES]; 2932 + 2933 + /* DCCG register programming variables */ 2934 + struct { 2935 + /* Core Display Clock Control */ 2936 + uint32_t dispclk_khz; /* DENTIST_DISPCLK_CNTL->DENTIST_DISPCLK_WDIVIDER from clk_mgr.dispclk_khz */ 2937 + uint32_t dc_mem_global_pwr_req_dis; /* DC_MEM_GLOBAL_PWR_REQ_CNTL->DC_MEM_GLOBAL_PWR_REQ_DIS from memory power management settings */ 2938 + 2939 + /* DPP Clock Control - 4 fields per pipe */ 2940 + uint32_t dppclk_khz[MAX_PIPES]; /* DPPCLK_CTRL->DPPCLK_R_GATE_DISABLE from dpp_clocks[pipe] */ 2941 + uint32_t dppclk_enable[MAX_PIPES]; /* DPPCLK_CTRL->DPPCLK0_EN,DPPCLK1_EN,DPPCLK2_EN,DPPCLK3_EN from dccg31_update_dpp_dto() */ 2942 + uint32_t dppclk_dto_enable[MAX_PIPES]; /* DPPCLK_DTO_CTRL->DPPCLK_DTO_ENABLE from dccg->dpp_clock_gated[dpp_inst] state */ 2943 + uint32_t dppclk_dto_phase[MAX_PIPES]; /* DPPCLK0_DTO_PARAM->DPPCLK0_DTO_PHASE from phase calculation req_dppclk/ref_dppclk */ 2944 + uint32_t dppclk_dto_modulo[MAX_PIPES]; /* DPPCLK0_DTO_PARAM->DPPCLK0_DTO_MODULO from modulo = 0xff */ 2945 + 2946 + /* DSC Clock Control - 4 fields per DSC resource */ 2947 + uint32_t dscclk_khz[MAX_PIPES]; /* DSCCLK_DTO_CTRL->DSCCLK_DTO_ENABLE from dsc_clocks */ 2948 + uint32_t dscclk_dto_enable[MAX_PIPES]; /* DSCCLK_DTO_CTRL->DSCCLK0_DTO_ENABLE,DSCCLK1_DTO_ENABLE,DSCCLK2_DTO_ENABLE,DSCCLK3_DTO_ENABLE */ 2949 + uint32_t dscclk_dto_phase[MAX_PIPES]; /* DSCCLK0_DTO_PARAM->DSCCLK0_DTO_PHASE from dccg31_enable_dscclk() */ 2950 + uint32_t dscclk_dto_modulo[MAX_PIPES]; /* DSCCLK0_DTO_PARAM->DSCCLK0_DTO_MODULO from dccg31_enable_dscclk() */ 2951 + 2952 + /* Pixel Clock Control - per pipe */ 2953 + uint32_t pixclk_khz[MAX_PIPES]; /* PIXCLK_RESYNC_CNTL->PIXCLK_RESYNC_ENABLE from stream.timing.pix_clk_100hz */ 2954 + uint32_t otg_pixel_rate_div[MAX_PIPES]; /* OTG_PIXEL_RATE_DIV->OTG_PIXEL_RATE_DIV from OTG pixel rate divider control */ 2955 + uint32_t dtbclk_dto_enable[MAX_PIPES]; /* OTG0_PIXEL_RATE_CNTL->DTBCLK_DTO_ENABLE from dccg31_set_dtbclk_dto() */ 2956 + uint32_t pipe_dto_src_sel[MAX_PIPES]; /* OTG0_PIXEL_RATE_CNTL->PIPE_DTO_SRC_SEL from dccg31_set_dtbclk_dto() source selection */ 2957 + uint32_t dtbclk_dto_div[MAX_PIPES]; /* OTG0_PIXEL_RATE_CNTL->DTBCLK_DTO_DIV from dtbdto_div calculation */ 2958 + uint32_t otg_add_pixel[MAX_PIPES]; /* OTG0_PIXEL_RATE_CNTL->OTG_ADD_PIXEL from dccg31_otg_add_pixel() */ 2959 + uint32_t otg_drop_pixel[MAX_PIPES]; /* OTG0_PIXEL_RATE_CNTL->OTG_DROP_PIXEL from dccg31_otg_drop_pixel() */ 2960 + 2961 + /* DTBCLK DTO Control - 4 DTOs */ 2962 + uint32_t dtbclk_dto_modulo[4]; /* DTBCLK_DTO0_MODULO->DTBCLK_DTO0_MODULO from dccg31_set_dtbclk_dto() modulo calculation */ 2963 + uint32_t dtbclk_dto_phase[4]; /* DTBCLK_DTO0_PHASE->DTBCLK_DTO0_PHASE from phase calculation pixclk_khz/ref_dtbclk_khz */ 2964 + uint32_t dtbclk_dto_dbuf_en; /* DTBCLK_DTO_DBUF_EN->DTBCLK DTO data buffer enable */ 2965 + 2966 + /* DP Stream Clock Control - 4 pipes */ 2967 + uint32_t dpstreamclk_enable[MAX_PIPES]; /* DPSTREAMCLK_CNTL->DPSTREAMCLK_PIPE0_EN,DPSTREAMCLK_PIPE1_EN,DPSTREAMCLK_PIPE2_EN,DPSTREAMCLK_PIPE3_EN */ 2968 + uint32_t dp_dto_modulo[4]; /* DP_DTO0_MODULO->DP_DTO0_MODULO from DP stream DTO programming */ 2969 + uint32_t dp_dto_phase[4]; /* DP_DTO0_PHASE->DP_DTO0_PHASE from DP stream DTO programming */ 2970 + uint32_t dp_dto_dbuf_en; /* DP_DTO_DBUF_EN->DP DTO data buffer enable */ 2971 + 2972 + /* PHY Symbol Clock Control - 5 PHYs (A,B,C,D,E) */ 2973 + uint32_t phy_symclk_force_en[5]; /* PHYASYMCLK_CLOCK_CNTL->PHYASYMCLK_FORCE_EN from dccg31_set_physymclk() force_enable */ 2974 + uint32_t phy_symclk_force_src_sel[5]; /* PHYASYMCLK_CLOCK_CNTL->PHYASYMCLK_FORCE_SRC_SEL from dccg31_set_physymclk() clk_src */ 2975 + uint32_t phy_symclk_gate_disable[5]; /* DCCG_GATE_DISABLE_CNTL2->PHYASYMCLK_GATE_DISABLE from debug.root_clock_optimization.bits.physymclk */ 2976 + 2977 + /* SYMCLK32 SE Control - 4 instances */ 2978 + uint32_t symclk32_se_src_sel[4]; /* SYMCLK32_SE_CNTL->SYMCLK32_SE0_SRC_SEL from dccg31_enable_symclk32_se() with get_phy_mux_symclk() mapping */ 2979 + uint32_t symclk32_se_enable[4]; /* SYMCLK32_SE_CNTL->SYMCLK32_SE0_EN from dccg31_enable_symclk32_se() enable */ 2980 + uint32_t symclk32_se_gate_disable[4]; /* DCCG_GATE_DISABLE_CNTL3->SYMCLK32_SE0_GATE_DISABLE from debug.root_clock_optimization.bits.symclk32_se */ 2981 + 2982 + /* SYMCLK32 LE Control - 2 instances */ 2983 + uint32_t symclk32_le_src_sel[2]; /* SYMCLK32_LE_CNTL->SYMCLK32_LE0_SRC_SEL from dccg31_enable_symclk32_le() phyd32clk source */ 2984 + uint32_t symclk32_le_enable[2]; /* SYMCLK32_LE_CNTL->SYMCLK32_LE0_EN from dccg31_enable_symclk32_le() enable */ 2985 + uint32_t symclk32_le_gate_disable[2]; /* DCCG_GATE_DISABLE_CNTL3->SYMCLK32_LE0_GATE_DISABLE from debug.root_clock_optimization.bits.symclk32_le */ 2986 + 2987 + /* DPIA Clock Control */ 2988 + uint32_t dpiaclk_540m_dto_modulo; /* DPIACLK_540M_DTO_MODULO->DPIA 540MHz DTO modulo */ 2989 + uint32_t dpiaclk_540m_dto_phase; /* DPIACLK_540M_DTO_PHASE->DPIA 540MHz DTO phase */ 2990 + uint32_t dpiaclk_810m_dto_modulo; /* DPIACLK_810M_DTO_MODULO->DPIA 810MHz DTO modulo */ 2991 + uint32_t dpiaclk_810m_dto_phase; /* DPIACLK_810M_DTO_PHASE->DPIA 810MHz DTO phase */ 2992 + uint32_t dpiaclk_dto_cntl; /* DPIACLK_DTO_CNTL->DPIA clock DTO control */ 2993 + uint32_t dpiasymclk_cntl; /* DPIASYMCLK_CNTL->DPIA symbol clock control */ 2994 + 2995 + /* Clock Gating Control */ 2996 + uint32_t dccg_gate_disable_cntl; /* DCCG_GATE_DISABLE_CNTL->Clock gate disable control from dccg31_init() */ 2997 + uint32_t dpstreamclk_gate_disable; /* DCCG_GATE_DISABLE_CNTL3->DPSTREAMCLK_GATE_DISABLE from debug.root_clock_optimization.bits.dpstream */ 2998 + uint32_t dpstreamclk_root_gate_disable; /* DCCG_GATE_DISABLE_CNTL3->DPSTREAMCLK_ROOT_GATE_DISABLE from debug.root_clock_optimization.bits.dpstream */ 2999 + 3000 + /* VSync Control */ 3001 + uint32_t vsync_cnt_ctrl; /* DCCG_VSYNC_CNT_CTRL->VSync counter control */ 3002 + uint32_t vsync_cnt_int_ctrl; /* DCCG_VSYNC_CNT_INT_CTRL->VSync counter interrupt control */ 3003 + uint32_t vsync_otg_latch_value[6]; /* DCCG_VSYNC_OTG0_LATCH_VALUE->OTG0 VSync latch value (for OTG0-5) */ 3004 + 3005 + /* Time Base Control */ 3006 + uint32_t microsecond_time_base_div; /* MICROSECOND_TIME_BASE_DIV->Microsecond time base divider */ 3007 + uint32_t millisecond_time_base_div; /* MILLISECOND_TIME_BASE_DIV->Millisecond time base divider */ 3008 + } dccg; 3009 + 3010 + /* DSC essential configuration for underflow analysis */ 3011 + struct { 3012 + /* DSC active state - critical for bandwidth analysis */ 3013 + uint32_t dsc_clock_enable; /* DSC enabled - affects bandwidth requirements */ 3014 + 3015 + /* DSC configuration affecting bandwidth and timing */ 3016 + uint32_t dsc_num_slices_h; /* Horizontal slice count - affects throughput */ 3017 + uint32_t dsc_num_slices_v; /* Vertical slice count - affects throughput */ 3018 + uint32_t dsc_bits_per_pixel; /* Compression ratio - affects bandwidth */ 3019 + 3020 + /* OPP integration - affects pipeline flow */ 3021 + uint32_t dscrm_dsc_forward_enable; /* DSC forwarding to OPP enabled */ 3022 + uint32_t dscrm_dsc_opp_pipe_source; /* Which OPP receives DSC output */ 3023 + } dsc[MAX_PIPES]; 3024 + 3025 + /* MPC register programming variables */ 3026 + struct { 3027 + /* MPCC blending tree and mode control */ 3028 + uint32_t mpcc_mode[MAX_PIPES]; /* MPCC_CONTROL->MPCC_MODE from blend_cfg.blend_mode */ 3029 + uint32_t mpcc_alpha_blend_mode[MAX_PIPES]; /* MPCC_CONTROL->MPCC_ALPHA_BLND_MODE from blend_cfg.alpha_mode */ 3030 + uint32_t mpcc_alpha_multiplied_mode[MAX_PIPES]; /* MPCC_CONTROL->MPCC_ALPHA_MULTIPLIED_MODE from blend_cfg.pre_multiplied_alpha */ 3031 + uint32_t mpcc_blnd_active_overlap_only[MAX_PIPES]; /* MPCC_CONTROL->MPCC_BLND_ACTIVE_OVERLAP_ONLY from blend_cfg.overlap_only */ 3032 + uint32_t mpcc_global_alpha[MAX_PIPES]; /* MPCC_CONTROL->MPCC_GLOBAL_ALPHA from blend_cfg.global_alpha */ 3033 + uint32_t mpcc_global_gain[MAX_PIPES]; /* MPCC_CONTROL->MPCC_GLOBAL_GAIN from blend_cfg.global_gain */ 3034 + uint32_t mpcc_bg_bpc[MAX_PIPES]; /* MPCC_CONTROL->MPCC_BG_BPC from background color depth */ 3035 + uint32_t mpcc_bot_gain_mode[MAX_PIPES]; /* MPCC_CONTROL->MPCC_BOT_GAIN_MODE from bottom layer gain control */ 3036 + 3037 + /* MPCC blending tree connections */ 3038 + uint32_t mpcc_bot_sel[MAX_PIPES]; /* MPCC_BOT_SEL->MPCC_BOT_SEL from mpcc_state->bot_sel */ 3039 + uint32_t mpcc_top_sel[MAX_PIPES]; /* MPCC_TOP_SEL->MPCC_TOP_SEL from mpcc_state->dpp_id */ 3040 + 3041 + /* MPCC output gamma control */ 3042 + uint32_t mpcc_ogam_mode[MAX_PIPES]; /* MPCC_OGAM_CONTROL->MPCC_OGAM_MODE from output gamma mode */ 3043 + uint32_t mpcc_ogam_select[MAX_PIPES]; /* MPCC_OGAM_CONTROL->MPCC_OGAM_SELECT from gamma LUT bank selection */ 3044 + uint32_t mpcc_ogam_pwl_disable[MAX_PIPES]; /* MPCC_OGAM_CONTROL->MPCC_OGAM_PWL_DISABLE from PWL control */ 3045 + 3046 + /* MPCC pipe assignment and status */ 3047 + uint32_t mpcc_opp_id[MAX_PIPES]; /* MPCC_OPP_ID->MPCC_OPP_ID from mpcc_state->opp_id */ 3048 + uint32_t mpcc_idle[MAX_PIPES]; /* MPCC_STATUS->MPCC_IDLE from mpcc idle status */ 3049 + uint32_t mpcc_busy[MAX_PIPES]; /* MPCC_STATUS->MPCC_BUSY from mpcc busy status */ 3050 + 3051 + /* MPC output processing */ 3052 + uint32_t mpc_out_csc_mode; /* MPC_OUT_CSC_COEF->MPC_OUT_CSC_MODE from output_csc */ 3053 + uint32_t mpc_out_gamma_mode; /* MPC_OUT_GAMMA_LUT->MPC_OUT_GAMMA_MODE from output_gamma */ 3054 + } mpc; 3055 + 3056 + /* OPP register programming variables for each pipe */ 3057 + struct { 3058 + /* Display Pattern Generator (DPG) Control - 19 fields from DPG_CONTROL register */ 3059 + uint32_t dpg_enable; /* DPG_CONTROL->DPG_EN from test_pattern parameter (enable/disable) */ 3060 + 3061 + /* Format Control (FMT) - 18 fields from FMT_CONTROL register */ 3062 + uint32_t fmt_pixel_encoding; /* FMT_CONTROL->FMT_PIXEL_ENCODING from clamping->pixel_encoding */ 3063 + uint32_t fmt_subsampling_mode; /* FMT_CONTROL->FMT_SUBSAMPLING_MODE from force_chroma_subsampling_1tap */ 3064 + uint32_t fmt_cbcr_bit_reduction_bypass; /* FMT_CONTROL->FMT_CBCR_BIT_REDUCTION_BYPASS from pixel_encoding bypass control */ 3065 + uint32_t fmt_stereosync_override; /* FMT_CONTROL->FMT_STEREOSYNC_OVERRIDE from stereo timing override */ 3066 + uint32_t fmt_spatial_dither_frame_counter_max; /* FMT_CONTROL->FMT_SPATIAL_DITHER_FRAME_COUNTER_MAX from fmt_bit_depth->flags */ 3067 + uint32_t fmt_spatial_dither_frame_counter_bit_swap; /* FMT_CONTROL->FMT_SPATIAL_DITHER_FRAME_COUNTER_BIT_SWAP from dither control */ 3068 + uint32_t fmt_truncate_enable; /* FMT_CONTROL->FMT_TRUNCATE_EN from fmt_bit_depth->flags.TRUNCATE_ENABLED */ 3069 + uint32_t fmt_truncate_depth; /* FMT_CONTROL->FMT_TRUNCATE_DEPTH from fmt_bit_depth->flags.TRUNCATE_DEPTH */ 3070 + uint32_t fmt_truncate_mode; /* FMT_CONTROL->FMT_TRUNCATE_MODE from fmt_bit_depth->flags.TRUNCATE_MODE */ 3071 + uint32_t fmt_spatial_dither_enable; /* FMT_CONTROL->FMT_SPATIAL_DITHER_EN from fmt_bit_depth->flags.SPATIAL_DITHER_ENABLED */ 3072 + uint32_t fmt_spatial_dither_mode; /* FMT_CONTROL->FMT_SPATIAL_DITHER_MODE from fmt_bit_depth->flags.SPATIAL_DITHER_MODE */ 3073 + uint32_t fmt_spatial_dither_depth; /* FMT_CONTROL->FMT_SPATIAL_DITHER_DEPTH from fmt_bit_depth->flags.SPATIAL_DITHER_DEPTH */ 3074 + uint32_t fmt_temporal_dither_enable; /* FMT_CONTROL->FMT_TEMPORAL_DITHER_EN from fmt_bit_depth->flags.TEMPORAL_DITHER_ENABLED */ 3075 + uint32_t fmt_clamp_data_enable; /* FMT_CONTROL->FMT_CLAMP_DATA_EN from clamping->clamping_range enable */ 3076 + uint32_t fmt_clamp_color_format; /* FMT_CONTROL->FMT_CLAMP_COLOR_FORMAT from clamping->color_format */ 3077 + uint32_t fmt_dynamic_exp_enable; /* FMT_CONTROL->FMT_DYNAMIC_EXP_EN from color_sp/color_dpth/signal */ 3078 + uint32_t fmt_dynamic_exp_mode; /* FMT_CONTROL->FMT_DYNAMIC_EXP_MODE from color space mode mapping */ 3079 + uint32_t fmt_bit_depth_control; /* Legacy field - kept for compatibility */ 3080 + 3081 + /* OPP Pipe Control - 1 field from OPP_PIPE_CONTROL register */ 3082 + uint32_t opp_pipe_clock_enable; /* OPP_PIPE_CONTROL->OPP_PIPE_CLOCK_EN from enable parameter (bool) */ 3083 + 3084 + /* OPP CRC Control - 3 fields from OPP_PIPE_CRC_CONTROL register */ 3085 + uint32_t opp_crc_enable; /* OPP_PIPE_CRC_CONTROL->CRC_EN from CRC enable control */ 3086 + uint32_t opp_crc_select_source; /* OPP_PIPE_CRC_CONTROL->CRC_SELECT_SOURCE from CRC source selection */ 3087 + uint32_t opp_crc_stereo_cont; /* OPP_PIPE_CRC_CONTROL->CRC_STEREO_CONT from stereo continuous CRC */ 3088 + 3089 + /* Output Buffer (OPPBUF) Control - 6 fields from OPPBUF_CONTROL register */ 3090 + uint32_t oppbuf_active_width; /* OPPBUF_CONTROL->OPPBUF_ACTIVE_WIDTH from oppbuf_params->active_width */ 3091 + uint32_t oppbuf_pixel_repetition; /* OPPBUF_CONTROL->OPPBUF_PIXEL_REPETITION from oppbuf_params->pixel_repetition */ 3092 + uint32_t oppbuf_display_segmentation; /* OPPBUF_CONTROL->OPPBUF_DISPLAY_SEGMENTATION from oppbuf_params->mso_segmentation */ 3093 + uint32_t oppbuf_overlap_pixel_num; /* OPPBUF_CONTROL->OPPBUF_OVERLAP_PIXEL_NUM from oppbuf_params->mso_overlap_pixel_num */ 3094 + uint32_t oppbuf_3d_vact_space1_size; /* OPPBUF_CONTROL->OPPBUF_3D_VACT_SPACE1_SIZE from 3D timing space1_size */ 3095 + uint32_t oppbuf_3d_vact_space2_size; /* OPPBUF_CONTROL->OPPBUF_3D_VACT_SPACE2_SIZE from 3D timing space2_size */ 3096 + 3097 + /* DSC Forward Config - 3 fields from DSCRM_DSC_FORWARD_CONFIG register */ 3098 + uint32_t dscrm_dsc_forward_enable; /* DSCRM_DSC_FORWARD_CONFIG->DSCRM_DSC_FORWARD_EN from DSC forward enable control */ 3099 + uint32_t dscrm_dsc_opp_pipe_source; /* DSCRM_DSC_FORWARD_CONFIG->DSCRM_DSC_OPP_PIPE_SOURCE from opp_pipe parameter */ 3100 + uint32_t dscrm_dsc_forward_enable_status; /* DSCRM_DSC_FORWARD_CONFIG->DSCRM_DSC_FORWARD_EN_STATUS from DSC forward status (read-only) */ 3101 + } opp[MAX_PIPES]; 3102 + 3103 + /* OPTC register programming variables for each pipe */ 3104 + struct { 3105 + uint32_t otg_master_inst; 3106 + 3107 + /* OTG_CONTROL register - 5 fields for OTG control */ 3108 + uint32_t otg_master_enable; /* OTG_CONTROL->OTG_MASTER_EN from timing enable/disable control */ 3109 + uint32_t otg_disable_point_cntl; /* OTG_CONTROL->OTG_DISABLE_POINT_CNTL from disable timing control */ 3110 + uint32_t otg_start_point_cntl; /* OTG_CONTROL->OTG_START_POINT_CNTL from start timing control */ 3111 + uint32_t otg_field_number_cntl; /* OTG_CONTROL->OTG_FIELD_NUMBER_CNTL from interlace field control */ 3112 + uint32_t otg_out_mux; /* OTG_CONTROL->OTG_OUT_MUX from output mux selection */ 3113 + 3114 + /* OTG Horizontal Timing - 7 fields */ 3115 + uint32_t otg_h_total; /* OTG_H_TOTAL->OTG_H_TOTAL from dc_crtc_timing->h_total */ 3116 + uint32_t otg_h_blank_start; /* OTG_H_BLANK_START_END->OTG_H_BLANK_START from dc_crtc_timing->h_front_porch */ 3117 + uint32_t otg_h_blank_end; /* OTG_H_BLANK_START_END->OTG_H_BLANK_END from dc_crtc_timing->h_addressable_video_pixel_width */ 3118 + uint32_t otg_h_sync_start; /* OTG_H_SYNC_A->OTG_H_SYNC_A_START from dc_crtc_timing->h_sync_width */ 3119 + uint32_t otg_h_sync_end; /* OTG_H_SYNC_A->OTG_H_SYNC_A_END from calculated sync end position */ 3120 + uint32_t otg_h_sync_polarity; /* OTG_H_SYNC_A_CNTL->OTG_H_SYNC_A_POL from dc_crtc_timing->flags.HSYNC_POSITIVE_POLARITY */ 3121 + uint32_t otg_h_timing_div_mode; /* OTG_H_TIMING_CNTL->OTG_H_TIMING_DIV_MODE from horizontal timing division mode */ 3122 + 3123 + /* OTG Vertical Timing - 7 fields */ 3124 + uint32_t otg_v_total; /* OTG_V_TOTAL->OTG_V_TOTAL from dc_crtc_timing->v_total */ 3125 + uint32_t otg_v_blank_start; /* OTG_V_BLANK_START_END->OTG_V_BLANK_START from dc_crtc_timing->v_front_porch */ 3126 + uint32_t otg_v_blank_end; /* OTG_V_BLANK_START_END->OTG_V_BLANK_END from dc_crtc_timing->v_addressable_video_line_width */ 3127 + uint32_t otg_v_sync_start; /* OTG_V_SYNC_A->OTG_V_SYNC_A_START from dc_crtc_timing->v_sync_width */ 3128 + uint32_t otg_v_sync_end; /* OTG_V_SYNC_A->OTG_V_SYNC_A_END from calculated sync end position */ 3129 + uint32_t otg_v_sync_polarity; /* OTG_V_SYNC_A_CNTL->OTG_V_SYNC_A_POL from dc_crtc_timing->flags.VSYNC_POSITIVE_POLARITY */ 3130 + uint32_t otg_v_sync_mode; /* OTG_V_SYNC_A_CNTL->OTG_V_SYNC_MODE from sync mode selection */ 3131 + 3132 + /* OTG DRR (Dynamic Refresh Rate) Control - 8 fields */ 3133 + uint32_t otg_v_total_max; /* OTG_V_TOTAL_MAX->OTG_V_TOTAL_MAX from drr_params->vertical_total_max */ 3134 + uint32_t otg_v_total_min; /* OTG_V_TOTAL_MIN->OTG_V_TOTAL_MIN from drr_params->vertical_total_min */ 3135 + uint32_t otg_v_total_mid; /* OTG_V_TOTAL_MID->OTG_V_TOTAL_MID from drr_params->vertical_total_mid */ 3136 + uint32_t otg_v_total_max_sel; /* OTG_V_TOTAL_CONTROL->OTG_V_TOTAL_MAX_SEL from DRR max selection enable */ 3137 + uint32_t otg_v_total_min_sel; /* OTG_V_TOTAL_CONTROL->OTG_V_TOTAL_MIN_SEL from DRR min selection enable */ 3138 + uint32_t otg_vtotal_mid_replacing_max_en; /* OTG_V_TOTAL_CONTROL->OTG_VTOTAL_MID_REPLACING_MAX_EN from DRR mid-frame enable */ 3139 + uint32_t otg_vtotal_mid_frame_num; /* OTG_V_TOTAL_CONTROL->OTG_VTOTAL_MID_FRAME_NUM from drr_params->vertical_total_mid_frame_num */ 3140 + uint32_t otg_set_v_total_min_mask; /* OTG_V_TOTAL_CONTROL->OTG_SET_V_TOTAL_MIN_MASK from DRR trigger mask */ 3141 + uint32_t otg_force_lock_on_event; /* OTG_V_TOTAL_CONTROL->OTG_FORCE_LOCK_ON_EVENT from DRR force lock control */ 3142 + 3143 + /* OPTC Data Source and ODM - 6 fields */ 3144 + uint32_t optc_seg0_src_sel; /* OPTC_DATA_SOURCE_SELECT->OPTC_SEG0_SRC_SEL from opp_id[0] ODM segment 0 source */ 3145 + uint32_t optc_seg1_src_sel; /* OPTC_DATA_SOURCE_SELECT->OPTC_SEG1_SRC_SEL from opp_id[1] ODM segment 1 source */ 3146 + uint32_t optc_seg2_src_sel; /* OPTC_DATA_SOURCE_SELECT->OPTC_SEG2_SRC_SEL from opp_id[2] ODM segment 2 source */ 3147 + uint32_t optc_seg3_src_sel; /* OPTC_DATA_SOURCE_SELECT->OPTC_SEG3_SRC_SEL from opp_id[3] ODM segment 3 source */ 3148 + uint32_t optc_num_of_input_segment; /* OPTC_DATA_SOURCE_SELECT->OPTC_NUM_OF_INPUT_SEGMENT from opp_cnt-1 number of input segments */ 3149 + uint32_t optc_mem_sel; /* OPTC_MEMORY_CONFIG->OPTC_MEM_SEL from memory_mask ODM memory selection */ 3150 + 3151 + /* OPTC Data Format and DSC - 4 fields */ 3152 + uint32_t optc_data_format; /* OPTC_DATA_FORMAT_CONTROL->OPTC_DATA_FORMAT from data format selection */ 3153 + uint32_t optc_dsc_mode; /* OPTC_DATA_FORMAT_CONTROL->OPTC_DSC_MODE from dsc_mode parameter */ 3154 + uint32_t optc_dsc_bytes_per_pixel; /* OPTC_BYTES_PER_PIXEL->OPTC_DSC_BYTES_PER_PIXEL from dsc_bytes_per_pixel parameter */ 3155 + uint32_t optc_segment_width; /* OPTC_WIDTH_CONTROL->OPTC_SEGMENT_WIDTH from segment_width parameter */ 3156 + uint32_t optc_dsc_slice_width; /* OPTC_WIDTH_CONTROL->OPTC_DSC_SLICE_WIDTH from dsc_slice_width parameter */ 3157 + 3158 + /* OPTC Clock and Underflow Control - 4 fields */ 3159 + uint32_t optc_input_pix_clk_en; /* OPTC_INPUT_CLOCK_CONTROL->OPTC_INPUT_PIX_CLK_EN from pixel clock enable */ 3160 + uint32_t optc_underflow_occurred_status; /* OPTC_INPUT_GLOBAL_CONTROL->OPTC_UNDERFLOW_OCCURRED_STATUS from underflow status (read-only) */ 3161 + uint32_t optc_underflow_clear; /* OPTC_INPUT_GLOBAL_CONTROL->OPTC_UNDERFLOW_CLEAR from underflow clear control */ 3162 + uint32_t otg_clock_enable; /* OTG_CLOCK_CONTROL->OTG_CLOCK_EN from OTG clock enable */ 3163 + uint32_t otg_clock_gate_dis; /* OTG_CLOCK_CONTROL->OTG_CLOCK_GATE_DIS from clock gate disable */ 3164 + 3165 + /* OTG Stereo and 3D Control - 6 fields */ 3166 + uint32_t otg_stereo_enable; /* OTG_STEREO_CONTROL->OTG_STEREO_EN from stereo enable control */ 3167 + uint32_t otg_stereo_sync_output_line_num; /* OTG_STEREO_CONTROL->OTG_STEREO_SYNC_OUTPUT_LINE_NUM from timing->stereo_3d_format line num */ 3168 + uint32_t otg_stereo_sync_output_polarity; /* OTG_STEREO_CONTROL->OTG_STEREO_SYNC_OUTPUT_POLARITY from stereo polarity control */ 3169 + uint32_t otg_3d_structure_en; /* OTG_3D_STRUCTURE_CONTROL->OTG_3D_STRUCTURE_EN from 3D structure enable */ 3170 + uint32_t otg_3d_structure_v_update_mode; /* OTG_3D_STRUCTURE_CONTROL->OTG_3D_STRUCTURE_V_UPDATE_MODE from 3D vertical update mode */ 3171 + uint32_t otg_3d_structure_stereo_sel_ovr; /* OTG_3D_STRUCTURE_CONTROL->OTG_3D_STRUCTURE_STEREO_SEL_OVR from 3D stereo selection override */ 3172 + uint32_t otg_interlace_enable; /* OTG_INTERLACE_CONTROL->OTG_INTERLACE_ENABLE from dc_crtc_timing->flags.INTERLACE */ 3173 + 3174 + /* OTG GSL (Global Sync Lock) Control - 5 fields */ 3175 + uint32_t otg_gsl0_en; /* OTG_GSL_CONTROL->OTG_GSL0_EN from GSL group 0 enable */ 3176 + uint32_t otg_gsl1_en; /* OTG_GSL_CONTROL->OTG_GSL1_EN from GSL group 1 enable */ 3177 + uint32_t otg_gsl2_en; /* OTG_GSL_CONTROL->OTG_GSL2_EN from GSL group 2 enable */ 3178 + uint32_t otg_gsl_master_en; /* OTG_GSL_CONTROL->OTG_GSL_MASTER_EN from GSL master enable */ 3179 + uint32_t otg_gsl_master_mode; /* OTG_GSL_CONTROL->OTG_GSL_MASTER_MODE from gsl_params->gsl_master mode */ 3180 + 3181 + /* OTG DRR Advanced Control - 4 fields */ 3182 + uint32_t otg_v_total_last_used_by_drr; /* OTG_DRR_CONTROL->OTG_V_TOTAL_LAST_USED_BY_DRR from last used DRR V_TOTAL (read-only) */ 3183 + uint32_t otg_drr_trigger_window_start_x; /* OTG_DRR_TRIGGER_WINDOW->OTG_DRR_TRIGGER_WINDOW_START_X from window_start parameter */ 3184 + uint32_t otg_drr_trigger_window_end_x; /* OTG_DRR_TRIGGER_WINDOW->OTG_DRR_TRIGGER_WINDOW_END_X from window_end parameter */ 3185 + uint32_t otg_drr_v_total_change_limit; /* OTG_DRR_V_TOTAL_CHANGE->OTG_DRR_V_TOTAL_CHANGE_LIMIT from limit parameter */ 3186 + 3187 + /* OTG DSC Position Control - 2 fields */ 3188 + uint32_t otg_dsc_start_position_x; /* OTG_DSC_START_POSITION->OTG_DSC_START_POSITION_X from DSC start X position */ 3189 + uint32_t otg_dsc_start_position_line_num; /* OTG_DSC_START_POSITION->OTG_DSC_START_POSITION_LINE_NUM from DSC start line number */ 3190 + 3191 + /* OTG Double Buffer Control - 2 fields */ 3192 + uint32_t otg_drr_timing_dbuf_update_mode; /* OTG_DOUBLE_BUFFER_CONTROL->OTG_DRR_TIMING_DBUF_UPDATE_MODE from DRR double buffer mode */ 3193 + uint32_t otg_blank_data_double_buffer_en; /* OTG_DOUBLE_BUFFER_CONTROL->OTG_BLANK_DATA_DOUBLE_BUFFER_EN from blank data double buffer enable */ 3194 + 3195 + /* OTG Vertical Interrupts - 6 fields */ 3196 + uint32_t otg_vertical_interrupt0_int_enable; /* OTG_VERTICAL_INTERRUPT0_CONTROL->OTG_VERTICAL_INTERRUPT0_INT_ENABLE from interrupt 0 enable */ 3197 + uint32_t otg_vertical_interrupt0_line_start; /* OTG_VERTICAL_INTERRUPT0_POSITION->OTG_VERTICAL_INTERRUPT0_LINE_START from start_line parameter */ 3198 + uint32_t otg_vertical_interrupt1_int_enable; /* OTG_VERTICAL_INTERRUPT1_CONTROL->OTG_VERTICAL_INTERRUPT1_INT_ENABLE from interrupt 1 enable */ 3199 + uint32_t otg_vertical_interrupt1_line_start; /* OTG_VERTICAL_INTERRUPT1_POSITION->OTG_VERTICAL_INTERRUPT1_LINE_START from start_line parameter */ 3200 + uint32_t otg_vertical_interrupt2_int_enable; /* OTG_VERTICAL_INTERRUPT2_CONTROL->OTG_VERTICAL_INTERRUPT2_INT_ENABLE from interrupt 2 enable */ 3201 + uint32_t otg_vertical_interrupt2_line_start; /* OTG_VERTICAL_INTERRUPT2_POSITION->OTG_VERTICAL_INTERRUPT2_LINE_START from start_line parameter */ 3202 + 3203 + /* OTG Global Sync Parameters - 6 fields */ 3204 + uint32_t otg_vready_offset; /* OTG_VREADY_PARAM->OTG_VREADY_OFFSET from vready_offset parameter */ 3205 + uint32_t otg_vstartup_start; /* OTG_VSTARTUP_PARAM->OTG_VSTARTUP_START from vstartup_start parameter */ 3206 + uint32_t otg_vupdate_offset; /* OTG_VUPDATE_PARAM->OTG_VUPDATE_OFFSET from vupdate_offset parameter */ 3207 + uint32_t otg_vupdate_width; /* OTG_VUPDATE_PARAM->OTG_VUPDATE_WIDTH from vupdate_width parameter */ 3208 + uint32_t master_update_lock_vupdate_keepout_start_offset; /* OTG_VUPDATE_KEEPOUT->MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET from pstate_keepout start */ 3209 + uint32_t master_update_lock_vupdate_keepout_end_offset; /* OTG_VUPDATE_KEEPOUT->MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET from pstate_keepout end */ 3210 + 3211 + /* OTG Manual Trigger Control - 11 fields */ 3212 + uint32_t otg_triga_source_select; /* OTG_TRIGA_CNTL->OTG_TRIGA_SOURCE_SELECT from trigger A source selection */ 3213 + uint32_t otg_triga_source_pipe_select; /* OTG_TRIGA_CNTL->OTG_TRIGA_SOURCE_PIPE_SELECT from trigger A pipe selection */ 3214 + uint32_t otg_triga_rising_edge_detect_cntl; /* OTG_TRIGA_CNTL->OTG_TRIGA_RISING_EDGE_DETECT_CNTL from trigger A rising edge detect */ 3215 + uint32_t otg_triga_falling_edge_detect_cntl; /* OTG_TRIGA_CNTL->OTG_TRIGA_FALLING_EDGE_DETECT_CNTL from trigger A falling edge detect */ 3216 + uint32_t otg_triga_polarity_select; /* OTG_TRIGA_CNTL->OTG_TRIGA_POLARITY_SELECT from trigger A polarity selection */ 3217 + uint32_t otg_triga_frequency_select; /* OTG_TRIGA_CNTL->OTG_TRIGA_FREQUENCY_SELECT from trigger A frequency selection */ 3218 + uint32_t otg_triga_delay; /* OTG_TRIGA_CNTL->OTG_TRIGA_DELAY from trigger A delay */ 3219 + uint32_t otg_triga_clear; /* OTG_TRIGA_CNTL->OTG_TRIGA_CLEAR from trigger A clear */ 3220 + uint32_t otg_triga_manual_trig; /* OTG_TRIGA_MANUAL_TRIG->OTG_TRIGA_MANUAL_TRIG from manual trigger A */ 3221 + uint32_t otg_trigb_source_select; /* OTG_TRIGB_CNTL->OTG_TRIGB_SOURCE_SELECT from trigger B source selection */ 3222 + uint32_t otg_trigb_polarity_select; /* OTG_TRIGB_CNTL->OTG_TRIGB_POLARITY_SELECT from trigger B polarity selection */ 3223 + uint32_t otg_trigb_manual_trig; /* OTG_TRIGB_MANUAL_TRIG->OTG_TRIGB_MANUAL_TRIG from manual trigger B */ 3224 + 3225 + /* OTG Static Screen and Update Control - 6 fields */ 3226 + uint32_t otg_static_screen_event_mask; /* OTG_STATIC_SCREEN_CONTROL->OTG_STATIC_SCREEN_EVENT_MASK from event_triggers parameter */ 3227 + uint32_t otg_static_screen_frame_count; /* OTG_STATIC_SCREEN_CONTROL->OTG_STATIC_SCREEN_FRAME_COUNT from num_frames parameter */ 3228 + uint32_t master_update_lock; /* OTG_MASTER_UPDATE_LOCK->MASTER_UPDATE_LOCK from update lock control */ 3229 + uint32_t master_update_mode; /* OTG_MASTER_UPDATE_MODE->MASTER_UPDATE_MODE from update mode selection */ 3230 + uint32_t otg_force_count_now_mode; /* OTG_FORCE_COUNT_NOW_CNTL->OTG_FORCE_COUNT_NOW_MODE from force count mode */ 3231 + uint32_t otg_force_count_now_clear; /* OTG_FORCE_COUNT_NOW_CNTL->OTG_FORCE_COUNT_NOW_CLEAR from force count clear */ 3232 + 3233 + /* VTG Control - 3 fields */ 3234 + uint32_t vtg0_enable; /* CONTROL->VTG0_ENABLE from VTG enable control */ 3235 + uint32_t vtg0_fp2; /* CONTROL->VTG0_FP2 from VTG front porch 2 */ 3236 + uint32_t vtg0_vcount_init; /* CONTROL->VTG0_VCOUNT_INIT from VTG vertical count init */ 3237 + 3238 + /* OTG Status (Read-Only) - 12 fields */ 3239 + uint32_t otg_v_blank; /* OTG_STATUS->OTG_V_BLANK from vertical blank status (read-only) */ 3240 + uint32_t otg_v_active_disp; /* OTG_STATUS->OTG_V_ACTIVE_DISP from vertical active display (read-only) */ 3241 + uint32_t otg_frame_count; /* OTG_STATUS_FRAME_COUNT->OTG_FRAME_COUNT from frame count (read-only) */ 3242 + uint32_t otg_horz_count; /* OTG_STATUS_POSITION->OTG_HORZ_COUNT from horizontal position (read-only) */ 3243 + uint32_t otg_vert_count; /* OTG_STATUS_POSITION->OTG_VERT_COUNT from vertical position (read-only) */ 3244 + uint32_t otg_horz_count_hv; /* OTG_STATUS_HV_COUNT->OTG_HORZ_COUNT from horizontal count (read-only) */ 3245 + uint32_t otg_vert_count_nom; /* OTG_STATUS_HV_COUNT->OTG_VERT_COUNT_NOM from vertical count nominal (read-only) */ 3246 + uint32_t otg_flip_pending; /* OTG_PIPE_UPDATE_STATUS->OTG_FLIP_PENDING from flip pending status (read-only) */ 3247 + uint32_t otg_dc_reg_update_pending; /* OTG_PIPE_UPDATE_STATUS->OTG_DC_REG_UPDATE_PENDING from DC register update pending (read-only) */ 3248 + uint32_t otg_cursor_update_pending; /* OTG_PIPE_UPDATE_STATUS->OTG_CURSOR_UPDATE_PENDING from cursor update pending (read-only) */ 3249 + uint32_t otg_vupdate_keepout_status; /* OTG_PIPE_UPDATE_STATUS->OTG_VUPDATE_KEEPOUT_STATUS from VUPDATE keepout status (read-only) */ 3250 + } optc[MAX_PIPES]; 3251 + 3252 + /* Metadata */ 3253 + uint32_t active_pipe_count; 3254 + uint32_t active_stream_count; 3255 + bool state_valid; 3256 + }; 3257 + 3258 + /** 3259 + * dc_capture_register_software_state() - Capture software state for register programming 3260 + * @dc: DC context containing current display configuration 3261 + * @state: Pointer to dc_register_software_state structure to populate 3262 + * 3263 + * Extracts all software state variables that are used to program hardware register 3264 + * fields across the display driver pipeline. This provides a complete snapshot 3265 + * of the software configuration that drives hardware register programming. 3266 + * 3267 + * The function traverses the DC context and extracts values from: 3268 + * - Stream configurations (timing, format, DSC settings) 3269 + * - Plane states (surface format, rotation, scaling, cursor) 3270 + * - Pipe contexts (resource allocation, blending, viewport) 3271 + * - Clock manager (display clocks, DPP clocks, pixel clocks) 3272 + * - Resource context (DET buffer allocation, ODM configuration) 3273 + * 3274 + * This is essential for underflow debugging as it captures the exact software 3275 + * state that determines how registers are programmed, allowing analysis of 3276 + * whether underflow is caused by incorrect register programming or timing issues. 3277 + * 3278 + * Return: true if state was successfully captured, false on error 3279 + */ 3280 + bool dc_capture_register_software_state(struct dc *dc, struct dc_register_software_state *state); 2795 3281 2796 3282 #endif /* DC_INTERFACE_H_ */
+36
drivers/gpu/drm/amd/display/dc/dc_dp_types.h
··· 1157 1157 bool cable_id_written; 1158 1158 }; 1159 1159 1160 + union dpcd_panel_replay_capability_supported { 1161 + struct { 1162 + unsigned char PANEL_REPLAY_SUPPORT :1; 1163 + unsigned char SELECTIVE_UPDATE_SUPPORT :1; 1164 + unsigned char EARLY_TRANSPORT_SUPPORT :1; 1165 + unsigned char RESERVED :5; 1166 + } bits; 1167 + unsigned char raw; 1168 + }; 1169 + 1160 1170 enum dpcd_downstream_port_max_bpc { 1161 1171 DOWN_STREAM_MAX_8BPC = 0, 1162 1172 DOWN_STREAM_MAX_10BPC, ··· 1290 1280 struct edp_psr_info psr_info; 1291 1281 1292 1282 struct replay_info pr_info; 1283 + union dpcd_panel_replay_capability_supported pr_caps_supported; 1293 1284 uint16_t edp_oled_emission_rate; 1294 1285 union dp_receive_port0_cap receive_port0_cap; 1295 1286 /* Indicates the number of SST links supported by MSO (Multi-Stream Output) */ ··· 1353 1342 unsigned char SINK_DEVICE_REPLAY_STATUS : 3; 1354 1343 unsigned char SINK_FRAME_LOCKED : 2; 1355 1344 unsigned char RESERVED : 1; 1345 + } bits; 1346 + unsigned char raw; 1347 + }; 1348 + 1349 + union panel_replay_enable_and_configuration_1 { 1350 + struct { 1351 + unsigned char PANEL_REPLAY_ENABLE :1; 1352 + unsigned char PANEL_REPLAY_CRC_ENABLE :1; 1353 + unsigned char IRQ_HPD_ASSDP_MISSING :1; 1354 + unsigned char IRQ_HPD_VSCSDP_UNCORRECTABLE_ERROR :1; 1355 + unsigned char IRQ_HPD_RFB_ERROR :1; 1356 + unsigned char IRQ_HPD_ACTIVE_FRAME_CRC_ERROR :1; 1357 + unsigned char PANEL_REPLAY_SELECTIVE_UPDATE_ENABLE :1; 1358 + unsigned char PANEL_REPLAY_EARLY_TRANSPORT_ENABLE :1; 1359 + } bits; 1360 + unsigned char raw; 1361 + }; 1362 + 1363 + union panel_replay_enable_and_configuration_2 { 1364 + struct { 1365 + unsigned char SINK_REFRESH_RATE_UNLOCK_GRANTED :1; 1366 + unsigned char RESERVED :1; 1367 + unsigned char SU_Y_GRANULARITY_EXT_VALUE_ENABLED :1; 1368 + unsigned char SU_Y_GRANULARITY_EXT_VALUE :4; 1369 + unsigned char SU_REGION_SCAN_LINE_CAPTURE_INDICATION :1; 1356 1370 } bits; 1357 1371 unsigned char raw; 1358 1372 };
+9
drivers/gpu/drm/amd/display/dc/dc_types.h
··· 941 941 DC_PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF, 942 942 }; 943 943 944 + enum dc_replay_version { 945 + DC_FREESYNC_REPLAY = 0, 946 + DC_VESA_PANEL_REPLAY = 1, 947 + DC_REPLAY_VERSION_UNSUPPORTED = 0XFF, 948 + }; 949 + 944 950 /* Possible values of display_endpoint_id.endpoint */ 945 951 enum display_endpoint_type { 946 952 DISPLAY_ENDPOINT_PHY = 0, /* Physical connector. */ ··· 1099 1093 Replay_Set_Residency_Frameupdate_Timer, 1100 1094 Replay_Set_Pseudo_VTotal, 1101 1095 Replay_Disabled_Adaptive_Sync_SDP, 1096 + Replay_Set_Version, 1102 1097 Replay_Set_General_Cmd, 1103 1098 }; 1104 1099 ··· 1135 1128 }; 1136 1129 1137 1130 struct replay_config { 1131 + /* Replay version */ 1132 + enum dc_replay_version replay_version; 1138 1133 /* Replay feature is supported */ 1139 1134 bool replay_supported; 1140 1135 /* Replay caps support DPCD & EDID caps*/
+2 -1
drivers/gpu/drm/amd/display/dc/dce/dce_audio.c
··· 1143 1143 REG_UPDATE(DCCG_AUDIO_DTO1_PHASE, 1144 1144 DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase); 1145 1145 1146 - REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 1146 + if (aud->masks->DCCG_AUDIO_DTO2_USE_512FBR_DTO) 1147 + REG_UPDATE(DCCG_AUDIO_DTO_SOURCE, 1147 1148 DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1); 1148 1149 1149 1150 }
+1 -1
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
··· 1568 1568 enc110->se_mask = se_mask; 1569 1569 } 1570 1570 1571 - static const struct stream_encoder_funcs dce110_an_str_enc_funcs = {0}; 1571 + static const struct stream_encoder_funcs dce110_an_str_enc_funcs = {}; 1572 1572 1573 1573 void dce110_analog_stream_encoder_construct( 1574 1574 struct dce110_stream_encoder *enc110,
+13
drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c
··· 387 387 cmd.replay_disabled_adaptive_sync_sdp.data.force_disabled = 388 388 cmd_element->disabled_adaptive_sync_sdp_data.force_disabled; 389 389 break; 390 + case Replay_Set_Version: 391 + //Header 392 + cmd.replay_set_version.header.sub_type = 393 + DMUB_CMD__REPLAY_SET_VERSION; 394 + cmd.replay_set_version.header.payload_bytes = 395 + sizeof(struct dmub_rb_cmd_replay_set_version) - 396 + sizeof(struct dmub_cmd_header); 397 + //Cmd Body 398 + cmd.replay_set_version.replay_set_version_data.panel_inst = 399 + cmd_element->version_data.panel_inst; 400 + cmd.replay_set_version.replay_set_version_data.version = 401 + cmd_element->version_data.version; 402 + break; 390 403 case Replay_Set_General_Cmd: 391 404 //Header 392 405 cmd.replay_set_general_cmd.header.sub_type =
+1 -1
drivers/gpu/drm/amd/display/dc/dml2_0/display_mode_core_structs.h
··· 1893 1893 struct CalculatePrefetchSchedule_params_st CalculatePrefetchSchedule_params; 1894 1894 }; 1895 1895 1896 - /// @brief Represent the overall soc/ip enviroment. It contains data structure represent the soc/ip characteristic and also structures that hold calculation output 1896 + /// @brief Represent the overall soc/ip environment. It contains data structure represent the soc/ip characteristic and also structures that hold calculation output 1897 1897 struct display_mode_lib_st { 1898 1898 dml_uint_t project; 1899 1899
+7 -3
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c
··· 685 685 uint32_t early_control = 0; 686 686 struct timing_generator *tg = pipe_ctx->stream_res.tg; 687 687 688 - link_hwss->setup_stream_attribute(pipe_ctx); 689 688 link_hwss->setup_stream_encoder(pipe_ctx); 690 689 691 690 dc->hwss.update_info_frame(pipe_ctx); ··· 1102 1103 if (!pipe_ctx->stream) 1103 1104 return; 1104 1105 1106 + if (dc_is_rgb_signal(pipe_ctx->stream->signal)) 1107 + return; 1108 + 1105 1109 dc = pipe_ctx->stream->ctx->dc; 1106 1110 clk_mgr = dc->clk_mgr; 1107 1111 link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res); ··· 1139 1137 const struct link_hwss *link_hwss; 1140 1138 1141 1139 if (!pipe_ctx || !pipe_ctx->stream) 1140 + return; 1141 + 1142 + if (dc_is_rgb_signal(pipe_ctx->stream->signal)) 1142 1143 return; 1143 1144 1144 1145 dc = pipe_ctx->stream->ctx->dc; ··· 1198 1193 pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( 1199 1194 pipe_ctx->stream_res.stream_enc); 1200 1195 1201 - if (!dc_is_rgb_signal(pipe_ctx->stream->signal)) 1202 - dc->hwss.disable_audio_stream(pipe_ctx); 1196 + dc->hwss.disable_audio_stream(pipe_ctx); 1203 1197 1204 1198 link_hwss->reset_stream_encoder(pipe_ctx); 1205 1199
+8 -2
drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
··· 614 614 * DOMAIN11_PGFSM_PWR_STATUS, pwr_status, 615 615 * 1, 1000); 616 616 */ 617 + 618 + /* Force disable cursor on plane powerdown on DPP 5 using dpp_force_disable_cursor */ 619 + if (!power_on) { 620 + struct dpp *dpp5 = hws->ctx->dc->res_pool->dpps[dpp_inst]; 621 + if (dpp5 && dpp5->funcs->dpp_force_disable_cursor) 622 + dpp5->funcs->dpp_force_disable_cursor(dpp5); 623 + } 624 + 617 625 break; 618 626 default: 619 627 BREAK_TO_DEBUGGER(); ··· 3062 3054 dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst, 3063 3055 link_enc->transmitter - TRANSMITTER_UNIPHY_A); 3064 3056 } 3065 - 3066 - link_hwss->setup_stream_attribute(pipe_ctx); 3067 3057 3068 3058 if (dc->res_pool->dccg->funcs->set_pixel_rate_div) 3069 3059 dc->res_pool->dccg->funcs->set_pixel_rate_div(
+2 -2
drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
··· 974 974 } 975 975 } 976 976 977 - link_hwss->setup_stream_attribute(pipe_ctx); 978 - 979 977 if (dc->res_pool->dccg->funcs->set_pixel_rate_div) { 980 978 dc->res_pool->dccg->funcs->set_pixel_rate_div( 981 979 dc->res_pool->dccg, ··· 3672 3674 if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed || 3673 3675 pipe_ctx->update_flags.bits.scaler || viewport_changed == true) && 3674 3676 pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { 3677 + 3678 + hwss_add_abort_cursor_offload_update(seq_state, dc, pipe_ctx); 3675 3679 3676 3680 hwss_add_set_cursor_attribute(seq_state, dc, pipe_ctx); 3677 3681
+13
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h
··· 696 696 struct mcache_regs_struct *mcache_regs; 697 697 }; 698 698 699 + struct abort_cursor_offload_update_params { 700 + struct dc *dc; 701 + struct pipe_ctx *pipe_ctx; 702 + }; 703 + 699 704 struct set_cursor_attribute_params { 700 705 struct dc *dc; 701 706 struct pipe_ctx *pipe_ctx; ··· 847 842 struct mpc_insert_plane_params mpc_insert_plane_params; 848 843 struct dpp_set_scaler_params dpp_set_scaler_params; 849 844 struct hubp_mem_program_viewport_params hubp_mem_program_viewport_params; 845 + struct abort_cursor_offload_update_params abort_cursor_offload_update_params; 850 846 struct set_cursor_attribute_params set_cursor_attribute_params; 851 847 struct set_cursor_position_params set_cursor_position_params; 852 848 struct set_cursor_sdr_white_level_params set_cursor_sdr_white_level_params; ··· 966 960 MPC_INSERT_PLANE, 967 961 DPP_SET_SCALER, 968 962 HUBP_MEM_PROGRAM_VIEWPORT, 963 + ABORT_CURSOR_OFFLOAD_UPDATE, 969 964 SET_CURSOR_ATTRIBUTE, 970 965 SET_CURSOR_POSITION, 971 966 SET_CURSOR_SDR_WHITE_LEVEL, ··· 1572 1565 1573 1566 void hwss_hubp_mem_program_viewport(union block_sequence_params *params); 1574 1567 1568 + void hwss_abort_cursor_offload_update(union block_sequence_params *params); 1569 + 1575 1570 void hwss_set_cursor_attribute(union block_sequence_params *params); 1576 1571 1577 1572 void hwss_set_cursor_position(union block_sequence_params *params); ··· 1969 1960 struct hubp *hubp, 1970 1961 const struct rect *viewport, 1971 1962 const struct rect *viewport_c); 1963 + 1964 + void hwss_add_abort_cursor_offload_update(struct block_sequence_state *seq_state, 1965 + struct dc *dc, 1966 + struct pipe_ctx *pipe_ctx); 1972 1967 1973 1968 void hwss_add_set_cursor_attribute(struct block_sequence_state *seq_state, 1974 1969 struct dc *dc,
+26
drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
··· 79 79 #define MAX_HPO_DP2_ENCODERS 4 80 80 #define MAX_HPO_DP2_LINK_ENCODERS 4 81 81 82 + /* Pipe topology snapshot structures */ 83 + #define MAX_TOPOLOGY_SNAPSHOTS 4 84 + 85 + struct pipe_topology_line { 86 + bool is_phantom_pipe; 87 + int plane_idx; 88 + int slice_idx; 89 + int stream_idx; 90 + int dpp_inst; 91 + int opp_inst; 92 + int tg_inst; 93 + }; 94 + 95 + struct pipe_topology_snapshot { 96 + struct pipe_topology_line pipe_log_lines[MAX_PIPES]; 97 + int line_count; 98 + uint64_t timestamp_us; 99 + int stream_count; 100 + int phantom_stream_count; 101 + }; 102 + 103 + struct pipe_topology_history { 104 + struct pipe_topology_snapshot snapshots[MAX_TOPOLOGY_SNAPSHOTS]; 105 + int current_snapshot_index; 106 + }; 107 + 82 108 struct gamma_curve { 83 109 uint32_t offset; 84 110 uint32_t segments_num;
+2 -1
drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
··· 227 227 #define LE_DCN401_REG_LIST_RI(id) \ 228 228 LE_DCN3_REG_LIST_RI(id), \ 229 229 SRI_ARR(DP_DPHY_INTERNAL_CTRL, DP, id), \ 230 - SRI_ARR(DIG_BE_CLK_CNTL, DIG, id) 230 + SRI_ARR(DIG_BE_CLK_CNTL, DIG, id),\ 231 + SR_ARR(DIO_CLK_CNTL, id) 231 232 232 233 /* DPP */ 233 234 #define DPP_REG_LIST_DCN401_COMMON_RI(id) \
-7
drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c
··· 44 44 struct dc_crtc_timing *crtc_timing, 45 45 bool is_dual_link) {} 46 46 47 - static void virtual_stream_encoder_lvds_set_stream_attribute( 48 - struct stream_encoder *enc, 49 - struct dc_crtc_timing *crtc_timing) 50 - {} 51 - 52 47 static void virtual_stream_encoder_set_throttled_vcp_size( 53 48 struct stream_encoder *enc, 54 49 struct fixed31_32 avg_time_slots_per_mtp) ··· 115 120 virtual_stream_encoder_hdmi_set_stream_attribute, 116 121 .dvi_set_stream_attribute = 117 122 virtual_stream_encoder_dvi_set_stream_attribute, 118 - .lvds_set_stream_attribute = 119 - virtual_stream_encoder_lvds_set_stream_attribute, 120 123 .set_throttled_vcp_size = 121 124 virtual_stream_encoder_set_throttled_vcp_size, 122 125 .update_hdmi_info_packets =
+1
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
··· 2647 2647 2648 2648 union dmub_cmd_fams2_config { 2649 2649 struct dmub_cmd_fams2_global_config global; 2650 + // coverity[cert_dcl37_c_violation:FALSE] errno.h, stddef.h, stdint.h not included in atombios.h 2650 2651 struct dmub_fams2_stream_static_state stream; //v0 2651 2652 union { 2652 2653 struct dmub_fams2_cmd_stream_static_base_state base;
+16
drivers/gpu/drm/amd/display/include/dpcd_defs.h
··· 30 30 #ifndef DP_SINK_HW_REVISION_START // can remove this once the define gets into linux drm_dp_helper.h 31 31 #define DP_SINK_HW_REVISION_START 0x409 32 32 #endif 33 + /* Panel Replay*/ 34 + #ifndef DP_PANEL_REPLAY_CAPABILITY_SUPPORT // can remove this once the define gets into linux drm_dp_helper.h 35 + #define DP_PANEL_REPLAY_CAPABILITY_SUPPORT 0x0b0 36 + #endif /* DP_PANEL_REPLAY_CAPABILITY_SUPPORT */ 37 + #ifndef DP_PANEL_REPLAY_CAPABILITY // can remove this once the define gets into linux drm_dp_helper.h 38 + #define DP_PANEL_REPLAY_CAPABILITY 0x0b1 39 + #endif /* DP_PANEL_REPLAY_CAPABILITY */ 40 + #ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 // can remove this once the define gets into linux drm_dp_helper.h 41 + #define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 0x1b0 42 + #endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_1 */ 43 + #ifndef DP_PANEL_REPLAY_ENABLE // can remove this once the define gets into linux drm_dp_helper.h 44 + #define DP_PANEL_REPLAY_ENABLE (1 << 0) 45 + #endif /* DP_PANEL_REPLAY_ENABLE */ 46 + #ifndef DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 // can remove this once the define gets into linux drm_dp_helper.h 47 + #define DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 0x1b1 48 + #endif /* DP_PANEL_REPLAY_ENABLE_AND_CONFIGURATION_2 */ 33 49 34 50 enum dpcd_revision { 35 51 DPCD_REV_10 = 0x10,
+3
drivers/gpu/drm/amd/display/modules/power/power_helpers.c
··· 1037 1037 uint8_t max_link_off_frame_count = 0; 1038 1038 uint16_t max_deviation_line = 0, pixel_deviation_per_line = 0; 1039 1039 1040 + if (!link || link->replay_settings.config.replay_version != DC_FREESYNC_REPLAY) 1041 + return; 1042 + 1040 1043 max_deviation_line = link->dpcd_caps.pr_info.max_deviation_line; 1041 1044 pixel_deviation_per_line = link->dpcd_caps.pr_info.pixel_deviation_per_line; 1042 1045
+9 -3
drivers/gpu/drm/amd/pm/amdgpu_dpm.c
··· 1187 1187 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1188 1188 int ret = 0; 1189 1189 1190 - if (!pp_funcs->get_pp_table) 1191 - return 0; 1190 + if (!table) 1191 + return -EINVAL; 1192 + 1193 + if (amdgpu_sriov_vf(adev) || !pp_funcs->get_pp_table || adev->scpm_enabled) 1194 + return -EOPNOTSUPP; 1192 1195 1193 1196 mutex_lock(&adev->pm.mutex); 1194 1197 ret = pp_funcs->get_pp_table(adev->powerplay.pp_handle, ··· 1718 1715 const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; 1719 1716 int ret = 0; 1720 1717 1721 - if (!pp_funcs->set_pp_table) 1718 + if (!buf || !size) 1719 + return -EINVAL; 1720 + 1721 + if (amdgpu_sriov_vf(adev) || !pp_funcs->set_pp_table || adev->scpm_enabled) 1722 1722 return -EOPNOTSUPP; 1723 1723 1724 1724 mutex_lock(&adev->pm.mutex);
+10 -1
drivers/gpu/drm/amd/pm/amdgpu_pm.c
··· 2506 2506 AMDGPU_DEVICE_ATTR_RO(pp_num_states, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), 2507 2507 AMDGPU_DEVICE_ATTR_RO(pp_cur_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), 2508 2508 AMDGPU_DEVICE_ATTR_RW(pp_force_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), 2509 - AMDGPU_DEVICE_ATTR_RW(pp_table, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), 2509 + AMDGPU_DEVICE_ATTR_RW(pp_table, ATTR_FLAG_BASIC), 2510 2510 AMDGPU_DEVICE_ATTR_RW(pp_dpm_sclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, 2511 2511 .attr_update = pp_dpm_clk_default_attr_update), 2512 2512 AMDGPU_DEVICE_ATTR_RW(pp_dpm_mclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF, ··· 2638 2638 if (amdgpu_dpm_get_apu_thermal_limit(adev, &limit) == 2639 2639 -EOPNOTSUPP) 2640 2640 *states = ATTR_STATE_UNSUPPORTED; 2641 + } else if (DEVICE_ATTR_IS(pp_table)) { 2642 + int ret; 2643 + char *tmp = NULL; 2644 + 2645 + ret = amdgpu_dpm_get_pp_table(adev, &tmp); 2646 + if (ret == -EOPNOTSUPP || !tmp) 2647 + *states = ATTR_STATE_UNSUPPORTED; 2648 + else 2649 + *states = ATTR_STATE_SUPPORTED; 2641 2650 } 2642 2651 2643 2652 switch (gc_ver) {
+4 -1
drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
··· 631 631 { 632 632 struct pp_hwmgr *hwmgr = handle; 633 633 634 - if (!hwmgr || !hwmgr->pm_en || !hwmgr->soft_pp_table) 634 + if (!hwmgr || !hwmgr->pm_en || !table) 635 635 return -EINVAL; 636 + 637 + if (!hwmgr->soft_pp_table) 638 + return -EOPNOTSUPP; 636 639 637 640 *table = (char *)hwmgr->soft_pp_table; 638 641 return hwmgr->soft_pp_table_size;
+6 -3
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
··· 634 634 return -EOPNOTSUPP; 635 635 636 636 if (!smu_table->power_play_table && !smu_table->hardcode_pptable) 637 - return -EINVAL; 637 + return -EOPNOTSUPP; 638 638 639 639 if (smu_table->hardcode_pptable) 640 640 *table = smu_table->hardcode_pptable; ··· 1669 1669 if (adev->in_suspend && smu_is_dpm_running(smu)) { 1670 1670 dev_info(adev->dev, "dpm has been enabled\n"); 1671 1671 ret = smu_system_features_control(smu, true); 1672 - if (ret) 1672 + if (ret) { 1673 1673 dev_err(adev->dev, "Failed system features control!\n"); 1674 - return ret; 1674 + return ret; 1675 + } 1676 + 1677 + return smu_enable_thermal_alert(smu); 1675 1678 } 1676 1679 break; 1677 1680 default:
+6 -1
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
··· 1022 1022 1023 1023 int smu_v11_0_disable_thermal_alert(struct smu_context *smu) 1024 1024 { 1025 - return amdgpu_irq_put(smu->adev, &smu->irq_source, 0); 1025 + int ret = 0; 1026 + 1027 + if (smu->smu_table.thermal_controller_type) 1028 + ret = amdgpu_irq_put(smu->adev, &smu->irq_source, 0); 1029 + 1030 + return ret; 1026 1031 } 1027 1032 1028 1033 static uint16_t convert_to_vddc(uint8_t vid)
-7
drivers/gpu/drm/radeon/radeon_fence.c
··· 360 360 if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) 361 361 return true; 362 362 363 - if (down_read_trylock(&rdev->exclusive_lock)) { 364 - radeon_fence_process(rdev, ring); 365 - up_read(&rdev->exclusive_lock); 366 - 367 - if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq) 368 - return true; 369 - } 370 363 return false; 371 364 } 372 365