diff options
author | Dave Airlie <airlied@redhat.com> | 2019-02-10 23:04:05 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-02-10 23:04:20 -0500 |
commit | f4bc54b532a62d8bee421ca06adb6d1b3e7ffaa9 (patch) | |
tree | 3b835f9bed6bd236fa1a6d5d0add836f25ca8262 /drivers/gpu | |
parent | 5ea3998d56346975c2701df18fb5b6e3ab5c8d9e (diff) | |
parent | 0461221316ec21e0a535a35fba3feb6ba75706e6 (diff) |
Merge branch 'drm-next-5.1' of git://people.freedesktop.org/~agd5f/linux into drm-next
Updates for 5.1:
- GDS fixes
- Add AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES interface
- GPUVM fixes
- PCIE DPM switching fixes for vega20
- Vega10 uclk DPM regression fix
- DC Freesync fixes
- DC ABM fixes
- Various DC cleanups
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Alex Deucher <alexdeucher@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190208210214.27666-1-alexander.deucher@amd.com
Diffstat (limited to 'drivers/gpu')
50 files changed, 1155 insertions, 486 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1c49b8266d69..52a5e4fdc95b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | |||
@@ -214,6 +214,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, union drm_amdgpu_cs | |||
214 | case AMDGPU_CHUNK_ID_DEPENDENCIES: | 214 | case AMDGPU_CHUNK_ID_DEPENDENCIES: |
215 | case AMDGPU_CHUNK_ID_SYNCOBJ_IN: | 215 | case AMDGPU_CHUNK_ID_SYNCOBJ_IN: |
216 | case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: | 216 | case AMDGPU_CHUNK_ID_SYNCOBJ_OUT: |
217 | case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES: | ||
217 | break; | 218 | break; |
218 | 219 | ||
219 | default: | 220 | default: |
@@ -1090,6 +1091,15 @@ static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p, | |||
1090 | 1091 | ||
1091 | fence = amdgpu_ctx_get_fence(ctx, entity, | 1092 | fence = amdgpu_ctx_get_fence(ctx, entity, |
1092 | deps[i].handle); | 1093 | deps[i].handle); |
1094 | |||
1095 | if (chunk->chunk_id == AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES) { | ||
1096 | struct drm_sched_fence *s_fence = to_drm_sched_fence(fence); | ||
1097 | struct dma_fence *old = fence; | ||
1098 | |||
1099 | fence = dma_fence_get(&s_fence->scheduled); | ||
1100 | dma_fence_put(old); | ||
1101 | } | ||
1102 | |||
1093 | if (IS_ERR(fence)) { | 1103 | if (IS_ERR(fence)) { |
1094 | r = PTR_ERR(fence); | 1104 | r = PTR_ERR(fence); |
1095 | amdgpu_ctx_put(ctx); | 1105 | amdgpu_ctx_put(ctx); |
@@ -1177,7 +1187,8 @@ static int amdgpu_cs_dependencies(struct amdgpu_device *adev, | |||
1177 | 1187 | ||
1178 | chunk = &p->chunks[i]; | 1188 | chunk = &p->chunks[i]; |
1179 | 1189 | ||
1180 | if (chunk->chunk_id == AMDGPU_CHUNK_ID_DEPENDENCIES) { | 1190 | if (chunk->chunk_id == AMDGPU_CHUNK_ID_DEPENDENCIES || |
1191 | chunk->chunk_id == AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES) { | ||
1181 | r = amdgpu_cs_process_fence_dep(p, chunk); | 1192 | r = amdgpu_cs_process_fence_dep(p, chunk); |
1182 | if (r) | 1193 | if (r) |
1183 | return r; | 1194 | return r; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 384272603b21..4f8fb4ecde34 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
@@ -3618,6 +3618,38 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ | |||
3618 | return r; | 3618 | return r; |
3619 | } | 3619 | } |
3620 | 3620 | ||
3621 | static void amdgpu_device_get_min_pci_speed_width(struct amdgpu_device *adev, | ||
3622 | enum pci_bus_speed *speed, | ||
3623 | enum pcie_link_width *width) | ||
3624 | { | ||
3625 | struct pci_dev *pdev = adev->pdev; | ||
3626 | enum pci_bus_speed cur_speed; | ||
3627 | enum pcie_link_width cur_width; | ||
3628 | |||
3629 | *speed = PCI_SPEED_UNKNOWN; | ||
3630 | *width = PCIE_LNK_WIDTH_UNKNOWN; | ||
3631 | |||
3632 | while (pdev) { | ||
3633 | cur_speed = pcie_get_speed_cap(pdev); | ||
3634 | cur_width = pcie_get_width_cap(pdev); | ||
3635 | |||
3636 | if (cur_speed != PCI_SPEED_UNKNOWN) { | ||
3637 | if (*speed == PCI_SPEED_UNKNOWN) | ||
3638 | *speed = cur_speed; | ||
3639 | else if (cur_speed < *speed) | ||
3640 | *speed = cur_speed; | ||
3641 | } | ||
3642 | |||
3643 | if (cur_width != PCIE_LNK_WIDTH_UNKNOWN) { | ||
3644 | if (*width == PCIE_LNK_WIDTH_UNKNOWN) | ||
3645 | *width = cur_width; | ||
3646 | else if (cur_width < *width) | ||
3647 | *width = cur_width; | ||
3648 | } | ||
3649 | pdev = pci_upstream_bridge(pdev); | ||
3650 | } | ||
3651 | } | ||
3652 | |||
3621 | /** | 3653 | /** |
3622 | * amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot | 3654 | * amdgpu_device_get_pcie_info - fence pcie info about the PCIE slot |
3623 | * | 3655 | * |
@@ -3630,8 +3662,8 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ | |||
3630 | static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) | 3662 | static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) |
3631 | { | 3663 | { |
3632 | struct pci_dev *pdev; | 3664 | struct pci_dev *pdev; |
3633 | enum pci_bus_speed speed_cap; | 3665 | enum pci_bus_speed speed_cap, platform_speed_cap; |
3634 | enum pcie_link_width link_width; | 3666 | enum pcie_link_width platform_link_width; |
3635 | 3667 | ||
3636 | if (amdgpu_pcie_gen_cap) | 3668 | if (amdgpu_pcie_gen_cap) |
3637 | adev->pm.pcie_gen_mask = amdgpu_pcie_gen_cap; | 3669 | adev->pm.pcie_gen_mask = amdgpu_pcie_gen_cap; |
@@ -3648,6 +3680,12 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) | |||
3648 | return; | 3680 | return; |
3649 | } | 3681 | } |
3650 | 3682 | ||
3683 | if (adev->pm.pcie_gen_mask && adev->pm.pcie_mlw_mask) | ||
3684 | return; | ||
3685 | |||
3686 | amdgpu_device_get_min_pci_speed_width(adev, &platform_speed_cap, | ||
3687 | &platform_link_width); | ||
3688 | |||
3651 | if (adev->pm.pcie_gen_mask == 0) { | 3689 | if (adev->pm.pcie_gen_mask == 0) { |
3652 | /* asic caps */ | 3690 | /* asic caps */ |
3653 | pdev = adev->pdev; | 3691 | pdev = adev->pdev; |
@@ -3673,22 +3711,20 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) | |||
3673 | adev->pm.pcie_gen_mask |= CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1; | 3711 | adev->pm.pcie_gen_mask |= CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1; |
3674 | } | 3712 | } |
3675 | /* platform caps */ | 3713 | /* platform caps */ |
3676 | pdev = adev->ddev->pdev->bus->self; | 3714 | if (platform_speed_cap == PCI_SPEED_UNKNOWN) { |
3677 | speed_cap = pcie_get_speed_cap(pdev); | ||
3678 | if (speed_cap == PCI_SPEED_UNKNOWN) { | ||
3679 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | | 3715 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | |
3680 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2); | 3716 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2); |
3681 | } else { | 3717 | } else { |
3682 | if (speed_cap == PCIE_SPEED_16_0GT) | 3718 | if (platform_speed_cap == PCIE_SPEED_16_0GT) |
3683 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | | 3719 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | |
3684 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | | 3720 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | |
3685 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 | | 3721 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 | |
3686 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4); | 3722 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4); |
3687 | else if (speed_cap == PCIE_SPEED_8_0GT) | 3723 | else if (platform_speed_cap == PCIE_SPEED_8_0GT) |
3688 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | | 3724 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | |
3689 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | | 3725 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | |
3690 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3); | 3726 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3); |
3691 | else if (speed_cap == PCIE_SPEED_5_0GT) | 3727 | else if (platform_speed_cap == PCIE_SPEED_5_0GT) |
3692 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | | 3728 | adev->pm.pcie_gen_mask |= (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 | |
3693 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2); | 3729 | CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2); |
3694 | else | 3730 | else |
@@ -3697,12 +3733,10 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) | |||
3697 | } | 3733 | } |
3698 | } | 3734 | } |
3699 | if (adev->pm.pcie_mlw_mask == 0) { | 3735 | if (adev->pm.pcie_mlw_mask == 0) { |
3700 | pdev = adev->ddev->pdev->bus->self; | 3736 | if (platform_link_width == PCIE_LNK_WIDTH_UNKNOWN) { |
3701 | link_width = pcie_get_width_cap(pdev); | ||
3702 | if (link_width == PCIE_LNK_WIDTH_UNKNOWN) { | ||
3703 | adev->pm.pcie_mlw_mask |= AMDGPU_DEFAULT_PCIE_MLW_MASK; | 3737 | adev->pm.pcie_mlw_mask |= AMDGPU_DEFAULT_PCIE_MLW_MASK; |
3704 | } else { | 3738 | } else { |
3705 | switch (link_width) { | 3739 | switch (platform_link_width) { |
3706 | case PCIE_LNK_X32: | 3740 | case PCIE_LNK_X32: |
3707 | adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 | | 3741 | adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 | |
3708 | CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | | 3742 | CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index a1bb3773087b..7f3aa7b7e1d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | |||
@@ -71,9 +71,11 @@ | |||
71 | * - 3.25.0 - Add support for sensor query info (stable pstate sclk/mclk). | 71 | * - 3.25.0 - Add support for sensor query info (stable pstate sclk/mclk). |
72 | * - 3.26.0 - GFX9: Process AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE. | 72 | * - 3.26.0 - GFX9: Process AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE. |
73 | * - 3.27.0 - Add new chunk to to AMDGPU_CS to enable BO_LIST creation. | 73 | * - 3.27.0 - Add new chunk to to AMDGPU_CS to enable BO_LIST creation. |
74 | * - 3.28.0 - Add AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES | ||
75 | * - 3.29.0 - Add AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID | ||
74 | */ | 76 | */ |
75 | #define KMS_DRIVER_MAJOR 3 | 77 | #define KMS_DRIVER_MAJOR 3 |
76 | #define KMS_DRIVER_MINOR 27 | 78 | #define KMS_DRIVER_MINOR 29 |
77 | #define KMS_DRIVER_PATCHLEVEL 0 | 79 | #define KMS_DRIVER_PATCHLEVEL 0 |
78 | 80 | ||
79 | int amdgpu_vram_limit = 0; | 81 | int amdgpu_vram_limit = 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h index ecbcefe49a98..f89f5734d985 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gds.h | |||
@@ -37,6 +37,8 @@ struct amdgpu_gds { | |||
37 | struct amdgpu_gds_asic_info mem; | 37 | struct amdgpu_gds_asic_info mem; |
38 | struct amdgpu_gds_asic_info gws; | 38 | struct amdgpu_gds_asic_info gws; |
39 | struct amdgpu_gds_asic_info oa; | 39 | struct amdgpu_gds_asic_info oa; |
40 | uint32_t gds_compute_max_wave_id; | ||
41 | |||
40 | /* At present, GDS, GWS and OA resources for gfx (graphics) | 42 | /* At present, GDS, GWS and OA resources for gfx (graphics) |
41 | * is always pre-allocated and available for graphics operation. | 43 | * is always pre-allocated and available for graphics operation. |
42 | * Such resource is shared between all gfx clients. | 44 | * Such resource is shared between all gfx clients. |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index f4f00217546e..d21dd2f369da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | |||
@@ -54,10 +54,6 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, | |||
54 | 54 | ||
55 | memset(&bp, 0, sizeof(bp)); | 55 | memset(&bp, 0, sizeof(bp)); |
56 | *obj = NULL; | 56 | *obj = NULL; |
57 | /* At least align on page size */ | ||
58 | if (alignment < PAGE_SIZE) { | ||
59 | alignment = PAGE_SIZE; | ||
60 | } | ||
61 | 57 | ||
62 | bp.size = size; | 58 | bp.size = size; |
63 | bp.byte_align = alignment; | 59 | bp.byte_align = alignment; |
@@ -244,9 +240,6 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, | |||
244 | return -EINVAL; | 240 | return -EINVAL; |
245 | } | 241 | } |
246 | flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS; | 242 | flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS; |
247 | /* GDS allocations must be DW aligned */ | ||
248 | if (args->in.domains & AMDGPU_GEM_DOMAIN_GDS) | ||
249 | size = ALIGN(size, 4); | ||
250 | } | 243 | } |
251 | 244 | ||
252 | if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) { | 245 | if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 728e15e5d68a..fd9c4beeaaa4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | |||
@@ -426,12 +426,20 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, | |||
426 | size_t acc_size; | 426 | size_t acc_size; |
427 | int r; | 427 | int r; |
428 | 428 | ||
429 | page_align = roundup(bp->byte_align, PAGE_SIZE) >> PAGE_SHIFT; | 429 | /* Note that GDS/GWS/OA allocates 1 page per byte/resource. */ |
430 | if (bp->domain & (AMDGPU_GEM_DOMAIN_GDS | AMDGPU_GEM_DOMAIN_GWS | | 430 | if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) { |
431 | AMDGPU_GEM_DOMAIN_OA)) | 431 | /* GWS and OA don't need any alignment. */ |
432 | page_align = bp->byte_align; | ||
432 | size <<= PAGE_SHIFT; | 433 | size <<= PAGE_SHIFT; |
433 | else | 434 | } else if (bp->domain & AMDGPU_GEM_DOMAIN_GDS) { |
435 | /* Both size and alignment must be a multiple of 4. */ | ||
436 | page_align = ALIGN(bp->byte_align, 4); | ||
437 | size = ALIGN(size, 4) << PAGE_SHIFT; | ||
438 | } else { | ||
439 | /* Memory should be aligned at least to a page size. */ | ||
440 | page_align = ALIGN(bp->byte_align, PAGE_SIZE) >> PAGE_SHIFT; | ||
434 | size = ALIGN(size, PAGE_SIZE); | 441 | size = ALIGN(size, PAGE_SIZE); |
442 | } | ||
435 | 443 | ||
436 | if (!amdgpu_bo_validate_size(adev, size, bp->domain)) | 444 | if (!amdgpu_bo_validate_size(adev, size, bp->domain)) |
437 | return -ENOMEM; | 445 | return -ENOMEM; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index b852abb9db0f..73e71e61dc99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
@@ -1756,7 +1756,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1756 | } | 1756 | } |
1757 | 1757 | ||
1758 | r = amdgpu_bo_create_kernel(adev, adev->gds.mem.gfx_partition_size, | 1758 | r = amdgpu_bo_create_kernel(adev, adev->gds.mem.gfx_partition_size, |
1759 | PAGE_SIZE, AMDGPU_GEM_DOMAIN_GDS, | 1759 | 4, AMDGPU_GEM_DOMAIN_GDS, |
1760 | &adev->gds.gds_gfx_bo, NULL, NULL); | 1760 | &adev->gds.gds_gfx_bo, NULL, NULL); |
1761 | if (r) | 1761 | if (r) |
1762 | return r; | 1762 | return r; |
@@ -1769,7 +1769,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1769 | } | 1769 | } |
1770 | 1770 | ||
1771 | r = amdgpu_bo_create_kernel(adev, adev->gds.gws.gfx_partition_size, | 1771 | r = amdgpu_bo_create_kernel(adev, adev->gds.gws.gfx_partition_size, |
1772 | PAGE_SIZE, AMDGPU_GEM_DOMAIN_GWS, | 1772 | 1, AMDGPU_GEM_DOMAIN_GWS, |
1773 | &adev->gds.gws_gfx_bo, NULL, NULL); | 1773 | &adev->gds.gws_gfx_bo, NULL, NULL); |
1774 | if (r) | 1774 | if (r) |
1775 | return r; | 1775 | return r; |
@@ -1782,7 +1782,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) | |||
1782 | } | 1782 | } |
1783 | 1783 | ||
1784 | r = amdgpu_bo_create_kernel(adev, adev->gds.oa.gfx_partition_size, | 1784 | r = amdgpu_bo_create_kernel(adev, adev->gds.oa.gfx_partition_size, |
1785 | PAGE_SIZE, AMDGPU_GEM_DOMAIN_OA, | 1785 | 1, AMDGPU_GEM_DOMAIN_OA, |
1786 | &adev->gds.oa_gfx_bo, NULL, NULL); | 1786 | &adev->gds.oa_gfx_bo, NULL, NULL); |
1787 | if (r) | 1787 | if (r) |
1788 | return r; | 1788 | return r; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 0bc6f553dc08..75481cf3348f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
@@ -107,14 +107,6 @@ struct amdgpu_pte_update_params { | |||
107 | * DMA addresses to use for mapping, used during VM update by CPU | 107 | * DMA addresses to use for mapping, used during VM update by CPU |
108 | */ | 108 | */ |
109 | dma_addr_t *pages_addr; | 109 | dma_addr_t *pages_addr; |
110 | |||
111 | /** | ||
112 | * @kptr: | ||
113 | * | ||
114 | * Kernel pointer of PD/PT BO that needs to be updated, | ||
115 | * used during VM update by CPU | ||
116 | */ | ||
117 | void *kptr; | ||
118 | }; | 110 | }; |
119 | 111 | ||
120 | /** | 112 | /** |
@@ -1789,13 +1781,20 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
1789 | if (pages_addr) | 1781 | if (pages_addr) |
1790 | params.src = ~0; | 1782 | params.src = ~0; |
1791 | 1783 | ||
1792 | /* Wait for PT BOs to be free. PTs share the same resv. object | 1784 | /* Wait for PT BOs to be idle. PTs share the same resv. object |
1793 | * as the root PD BO | 1785 | * as the root PD BO |
1794 | */ | 1786 | */ |
1795 | r = amdgpu_vm_wait_pd(adev, vm, owner); | 1787 | r = amdgpu_vm_wait_pd(adev, vm, owner); |
1796 | if (unlikely(r)) | 1788 | if (unlikely(r)) |
1797 | return r; | 1789 | return r; |
1798 | 1790 | ||
1791 | /* Wait for any BO move to be completed */ | ||
1792 | if (exclusive) { | ||
1793 | r = dma_fence_wait(exclusive, true); | ||
1794 | if (unlikely(r)) | ||
1795 | return r; | ||
1796 | } | ||
1797 | |||
1799 | params.func = amdgpu_vm_cpu_set_ptes; | 1798 | params.func = amdgpu_vm_cpu_set_ptes; |
1800 | params.pages_addr = pages_addr; | 1799 | params.pages_addr = pages_addr; |
1801 | return amdgpu_vm_update_ptes(¶ms, start, last + 1, | 1800 | return amdgpu_vm_update_ptes(¶ms, start, last + 1, |
@@ -1809,13 +1808,12 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
1809 | /* | 1808 | /* |
1810 | * reserve space for two commands every (1 << BLOCK_SIZE) | 1809 | * reserve space for two commands every (1 << BLOCK_SIZE) |
1811 | * entries or 2k dwords (whatever is smaller) | 1810 | * entries or 2k dwords (whatever is smaller) |
1812 | * | ||
1813 | * The second command is for the shadow pagetables. | ||
1814 | */ | 1811 | */ |
1812 | ncmds = ((nptes >> min(adev->vm_manager.block_size, 11u)) + 1); | ||
1813 | |||
1814 | /* The second command is for the shadow pagetables. */ | ||
1815 | if (vm->root.base.bo->shadow) | 1815 | if (vm->root.base.bo->shadow) |
1816 | ncmds = ((nptes >> min(adev->vm_manager.block_size, 11u)) + 1) * 2; | 1816 | ncmds *= 2; |
1817 | else | ||
1818 | ncmds = ((nptes >> min(adev->vm_manager.block_size, 11u)) + 1); | ||
1819 | 1817 | ||
1820 | /* padding, etc. */ | 1818 | /* padding, etc. */ |
1821 | ndw = 64; | 1819 | ndw = 64; |
@@ -1834,10 +1832,11 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, | |||
1834 | ndw += ncmds * 10; | 1832 | ndw += ncmds * 10; |
1835 | 1833 | ||
1836 | /* extra commands for begin/end fragments */ | 1834 | /* extra commands for begin/end fragments */ |
1835 | ncmds = 2 * adev->vm_manager.fragment_size; | ||
1837 | if (vm->root.base.bo->shadow) | 1836 | if (vm->root.base.bo->shadow) |
1838 | ndw += 2 * 10 * adev->vm_manager.fragment_size * 2; | 1837 | ncmds *= 2; |
1839 | else | 1838 | |
1840 | ndw += 2 * 10 * adev->vm_manager.fragment_size; | 1839 | ndw += 10 * ncmds; |
1841 | 1840 | ||
1842 | params.func = amdgpu_vm_do_set_ptes; | 1841 | params.func = amdgpu_vm_do_set_ptes; |
1843 | } | 1842 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 0d90672d0e58..407dd16cc35c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | |||
@@ -125,7 +125,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) | |||
125 | if (!hive) { | 125 | if (!hive) { |
126 | ret = -EINVAL; | 126 | ret = -EINVAL; |
127 | dev_err(adev->dev, | 127 | dev_err(adev->dev, |
128 | "XGMI: node 0x%llx, can not matech hive 0x%llx in the hive list.\n", | 128 | "XGMI: node 0x%llx, can not match hive 0x%llx in the hive list.\n", |
129 | adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id); | 129 | adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id); |
130 | goto exit; | 130 | goto exit; |
131 | } | 131 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c index 7984292f9282..a59e0fdf5a97 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c | |||
@@ -2264,6 +2264,22 @@ static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring, | |||
2264 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); | 2264 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); |
2265 | u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24); | 2265 | u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24); |
2266 | 2266 | ||
2267 | /* Currently, there is a high possibility to get wave ID mismatch | ||
2268 | * between ME and GDS, leading to a hw deadlock, because ME generates | ||
2269 | * different wave IDs than the GDS expects. This situation happens | ||
2270 | * randomly when at least 5 compute pipes use GDS ordered append. | ||
2271 | * The wave IDs generated by ME are also wrong after suspend/resume. | ||
2272 | * Those are probably bugs somewhere else in the kernel driver. | ||
2273 | * | ||
2274 | * Writing GDS_COMPUTE_MAX_WAVE_ID resets wave ID counters in ME and | ||
2275 | * GDS to 0 for this ring (me/pipe). | ||
2276 | */ | ||
2277 | if (ib->flags & AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID) { | ||
2278 | amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
2279 | amdgpu_ring_write(ring, mmGDS_COMPUTE_MAX_WAVE_ID - PACKET3_SET_CONFIG_REG_START); | ||
2280 | amdgpu_ring_write(ring, ring->adev->gds.gds_compute_max_wave_id); | ||
2281 | } | ||
2282 | |||
2267 | amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 2283 | amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
2268 | amdgpu_ring_write(ring, | 2284 | amdgpu_ring_write(ring, |
2269 | #ifdef __BIG_ENDIAN | 2285 | #ifdef __BIG_ENDIAN |
@@ -5000,7 +5016,7 @@ static const struct amdgpu_ring_funcs gfx_v7_0_ring_funcs_compute = { | |||
5000 | 7 + /* gfx_v7_0_ring_emit_pipeline_sync */ | 5016 | 7 + /* gfx_v7_0_ring_emit_pipeline_sync */ |
5001 | CIK_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + /* gfx_v7_0_ring_emit_vm_flush */ | 5017 | CIK_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + /* gfx_v7_0_ring_emit_vm_flush */ |
5002 | 7 + 7 + 7, /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */ | 5018 | 7 + 7 + 7, /* gfx_v7_0_ring_emit_fence_compute x3 for user fence, vm fence */ |
5003 | .emit_ib_size = 4, /* gfx_v7_0_ring_emit_ib_compute */ | 5019 | .emit_ib_size = 7, /* gfx_v7_0_ring_emit_ib_compute */ |
5004 | .emit_ib = gfx_v7_0_ring_emit_ib_compute, | 5020 | .emit_ib = gfx_v7_0_ring_emit_ib_compute, |
5005 | .emit_fence = gfx_v7_0_ring_emit_fence_compute, | 5021 | .emit_fence = gfx_v7_0_ring_emit_fence_compute, |
5006 | .emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync, | 5022 | .emit_pipeline_sync = gfx_v7_0_ring_emit_pipeline_sync, |
@@ -5057,6 +5073,7 @@ static void gfx_v7_0_set_gds_init(struct amdgpu_device *adev) | |||
5057 | adev->gds.mem.total_size = RREG32(mmGDS_VMID0_SIZE); | 5073 | adev->gds.mem.total_size = RREG32(mmGDS_VMID0_SIZE); |
5058 | adev->gds.gws.total_size = 64; | 5074 | adev->gds.gws.total_size = 64; |
5059 | adev->gds.oa.total_size = 16; | 5075 | adev->gds.oa.total_size = 16; |
5076 | adev->gds.gds_compute_max_wave_id = RREG32(mmGDS_COMPUTE_MAX_WAVE_ID); | ||
5060 | 5077 | ||
5061 | if (adev->gds.mem.total_size == 64 * 1024) { | 5078 | if (adev->gds.mem.total_size == 64 * 1024) { |
5062 | adev->gds.mem.gfx_partition_size = 4096; | 5079 | adev->gds.mem.gfx_partition_size = 4096; |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index a26747681ed6..b8e50a34bdb3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | |||
@@ -6084,6 +6084,22 @@ static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring, | |||
6084 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); | 6084 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); |
6085 | u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24); | 6085 | u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24); |
6086 | 6086 | ||
6087 | /* Currently, there is a high possibility to get wave ID mismatch | ||
6088 | * between ME and GDS, leading to a hw deadlock, because ME generates | ||
6089 | * different wave IDs than the GDS expects. This situation happens | ||
6090 | * randomly when at least 5 compute pipes use GDS ordered append. | ||
6091 | * The wave IDs generated by ME are also wrong after suspend/resume. | ||
6092 | * Those are probably bugs somewhere else in the kernel driver. | ||
6093 | * | ||
6094 | * Writing GDS_COMPUTE_MAX_WAVE_ID resets wave ID counters in ME and | ||
6095 | * GDS to 0 for this ring (me/pipe). | ||
6096 | */ | ||
6097 | if (ib->flags & AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID) { | ||
6098 | amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
6099 | amdgpu_ring_write(ring, mmGDS_COMPUTE_MAX_WAVE_ID - PACKET3_SET_CONFIG_REG_START); | ||
6100 | amdgpu_ring_write(ring, ring->adev->gds.gds_compute_max_wave_id); | ||
6101 | } | ||
6102 | |||
6087 | amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 6103 | amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
6088 | amdgpu_ring_write(ring, | 6104 | amdgpu_ring_write(ring, |
6089 | #ifdef __BIG_ENDIAN | 6105 | #ifdef __BIG_ENDIAN |
@@ -6890,7 +6906,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { | |||
6890 | 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ | 6906 | 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ |
6891 | VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + /* gfx_v8_0_ring_emit_vm_flush */ | 6907 | VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 7 + /* gfx_v8_0_ring_emit_vm_flush */ |
6892 | 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */ | 6908 | 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_compute x3 for user fence, vm fence */ |
6893 | .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */ | 6909 | .emit_ib_size = 7, /* gfx_v8_0_ring_emit_ib_compute */ |
6894 | .emit_ib = gfx_v8_0_ring_emit_ib_compute, | 6910 | .emit_ib = gfx_v8_0_ring_emit_ib_compute, |
6895 | .emit_fence = gfx_v8_0_ring_emit_fence_compute, | 6911 | .emit_fence = gfx_v8_0_ring_emit_fence_compute, |
6896 | .emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync, | 6912 | .emit_pipeline_sync = gfx_v8_0_ring_emit_pipeline_sync, |
@@ -6920,7 +6936,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = { | |||
6920 | 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ | 6936 | 7 + /* gfx_v8_0_ring_emit_pipeline_sync */ |
6921 | 17 + /* gfx_v8_0_ring_emit_vm_flush */ | 6937 | 17 + /* gfx_v8_0_ring_emit_vm_flush */ |
6922 | 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence, vm fence */ | 6938 | 7 + 7 + 7, /* gfx_v8_0_ring_emit_fence_kiq x3 for user fence, vm fence */ |
6923 | .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_compute */ | 6939 | .emit_ib_size = 7, /* gfx_v8_0_ring_emit_ib_compute */ |
6924 | .emit_fence = gfx_v8_0_ring_emit_fence_kiq, | 6940 | .emit_fence = gfx_v8_0_ring_emit_fence_kiq, |
6925 | .test_ring = gfx_v8_0_ring_test_ring, | 6941 | .test_ring = gfx_v8_0_ring_test_ring, |
6926 | .insert_nop = amdgpu_ring_insert_nop, | 6942 | .insert_nop = amdgpu_ring_insert_nop, |
@@ -6996,6 +7012,7 @@ static void gfx_v8_0_set_gds_init(struct amdgpu_device *adev) | |||
6996 | adev->gds.mem.total_size = RREG32(mmGDS_VMID0_SIZE); | 7012 | adev->gds.mem.total_size = RREG32(mmGDS_VMID0_SIZE); |
6997 | adev->gds.gws.total_size = 64; | 7013 | adev->gds.gws.total_size = 64; |
6998 | adev->gds.oa.total_size = 16; | 7014 | adev->gds.oa.total_size = 16; |
7015 | adev->gds.gds_compute_max_wave_id = RREG32(mmGDS_COMPUTE_MAX_WAVE_ID); | ||
6999 | 7016 | ||
7000 | if (adev->gds.mem.total_size == 64 * 1024) { | 7017 | if (adev->gds.mem.total_size == 64 * 1024) { |
7001 | adev->gds.mem.gfx_partition_size = 4096; | 7018 | adev->gds.mem.gfx_partition_size = 4096; |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 262ee3cf6f1c..5533f6e4f4a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | |||
@@ -4010,6 +4010,22 @@ static void gfx_v9_0_ring_emit_ib_compute(struct amdgpu_ring *ring, | |||
4010 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); | 4010 | unsigned vmid = AMDGPU_JOB_GET_VMID(job); |
4011 | u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24); | 4011 | u32 control = INDIRECT_BUFFER_VALID | ib->length_dw | (vmid << 24); |
4012 | 4012 | ||
4013 | /* Currently, there is a high possibility to get wave ID mismatch | ||
4014 | * between ME and GDS, leading to a hw deadlock, because ME generates | ||
4015 | * different wave IDs than the GDS expects. This situation happens | ||
4016 | * randomly when at least 5 compute pipes use GDS ordered append. | ||
4017 | * The wave IDs generated by ME are also wrong after suspend/resume. | ||
4018 | * Those are probably bugs somewhere else in the kernel driver. | ||
4019 | * | ||
4020 | * Writing GDS_COMPUTE_MAX_WAVE_ID resets wave ID counters in ME and | ||
4021 | * GDS to 0 for this ring (me/pipe). | ||
4022 | */ | ||
4023 | if (ib->flags & AMDGPU_IB_FLAG_RESET_GDS_MAX_WAVE_ID) { | ||
4024 | amdgpu_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); | ||
4025 | amdgpu_ring_write(ring, mmGDS_COMPUTE_MAX_WAVE_ID); | ||
4026 | amdgpu_ring_write(ring, ring->adev->gds.gds_compute_max_wave_id); | ||
4027 | } | ||
4028 | |||
4013 | amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); | 4029 | amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); |
4014 | BUG_ON(ib->gpu_addr & 0x3); /* Dword align */ | 4030 | BUG_ON(ib->gpu_addr & 0x3); /* Dword align */ |
4015 | amdgpu_ring_write(ring, | 4031 | amdgpu_ring_write(ring, |
@@ -4729,7 +4745,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = { | |||
4729 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + | 4745 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + |
4730 | 2 + /* gfx_v9_0_ring_emit_vm_flush */ | 4746 | 2 + /* gfx_v9_0_ring_emit_vm_flush */ |
4731 | 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */ | 4747 | 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */ |
4732 | .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_compute */ | 4748 | .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */ |
4733 | .emit_ib = gfx_v9_0_ring_emit_ib_compute, | 4749 | .emit_ib = gfx_v9_0_ring_emit_ib_compute, |
4734 | .emit_fence = gfx_v9_0_ring_emit_fence, | 4750 | .emit_fence = gfx_v9_0_ring_emit_fence, |
4735 | .emit_pipeline_sync = gfx_v9_0_ring_emit_pipeline_sync, | 4751 | .emit_pipeline_sync = gfx_v9_0_ring_emit_pipeline_sync, |
@@ -4764,7 +4780,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = { | |||
4764 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + | 4780 | SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 + |
4765 | 2 + /* gfx_v9_0_ring_emit_vm_flush */ | 4781 | 2 + /* gfx_v9_0_ring_emit_vm_flush */ |
4766 | 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */ | 4782 | 8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */ |
4767 | .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_compute */ | 4783 | .emit_ib_size = 7, /* gfx_v9_0_ring_emit_ib_compute */ |
4768 | .emit_fence = gfx_v9_0_ring_emit_fence_kiq, | 4784 | .emit_fence = gfx_v9_0_ring_emit_fence_kiq, |
4769 | .test_ring = gfx_v9_0_ring_test_ring, | 4785 | .test_ring = gfx_v9_0_ring_test_ring, |
4770 | .insert_nop = amdgpu_ring_insert_nop, | 4786 | .insert_nop = amdgpu_ring_insert_nop, |
@@ -4846,6 +4862,26 @@ static void gfx_v9_0_set_gds_init(struct amdgpu_device *adev) | |||
4846 | break; | 4862 | break; |
4847 | } | 4863 | } |
4848 | 4864 | ||
4865 | switch (adev->asic_type) { | ||
4866 | case CHIP_VEGA10: | ||
4867 | case CHIP_VEGA20: | ||
4868 | adev->gds.gds_compute_max_wave_id = 0x7ff; | ||
4869 | break; | ||
4870 | case CHIP_VEGA12: | ||
4871 | adev->gds.gds_compute_max_wave_id = 0x27f; | ||
4872 | break; | ||
4873 | case CHIP_RAVEN: | ||
4874 | if (adev->rev_id >= 0x8) | ||
4875 | adev->gds.gds_compute_max_wave_id = 0x77; /* raven2 */ | ||
4876 | else | ||
4877 | adev->gds.gds_compute_max_wave_id = 0x15f; /* raven1 */ | ||
4878 | break; | ||
4879 | default: | ||
4880 | /* this really depends on the chip */ | ||
4881 | adev->gds.gds_compute_max_wave_id = 0x7ff; | ||
4882 | break; | ||
4883 | } | ||
4884 | |||
4849 | adev->gds.gws.total_size = 64; | 4885 | adev->gds.gws.total_size = 64; |
4850 | adev->gds.oa.total_size = 16; | 4886 | adev->gds.oa.total_size = 16; |
4851 | 4887 | ||
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 1923f47d3dd6..ad31d7b9912f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
@@ -2297,12 +2297,15 @@ static bool fill_plane_dcc_attributes(struct amdgpu_device *adev, | |||
2297 | uint64_t info) | 2297 | uint64_t info) |
2298 | { | 2298 | { |
2299 | struct dc *dc = adev->dm.dc; | 2299 | struct dc *dc = adev->dm.dc; |
2300 | struct dc_dcc_surface_param input = {0}; | 2300 | struct dc_dcc_surface_param input; |
2301 | struct dc_surface_dcc_cap output = {0}; | 2301 | struct dc_surface_dcc_cap output; |
2302 | uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B); | 2302 | uint32_t offset = AMDGPU_TILING_GET(info, DCC_OFFSET_256B); |
2303 | uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0; | 2303 | uint32_t i64b = AMDGPU_TILING_GET(info, DCC_INDEPENDENT_64B) != 0; |
2304 | uint64_t dcc_address; | 2304 | uint64_t dcc_address; |
2305 | 2305 | ||
2306 | memset(&input, 0, sizeof(input)); | ||
2307 | memset(&output, 0, sizeof(output)); | ||
2308 | |||
2306 | if (!offset) | 2309 | if (!offset) |
2307 | return false; | 2310 | return false; |
2308 | 2311 | ||
@@ -2956,11 +2959,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, | |||
2956 | drm_connector = &aconnector->base; | 2959 | drm_connector = &aconnector->base; |
2957 | 2960 | ||
2958 | if (!aconnector->dc_sink) { | 2961 | if (!aconnector->dc_sink) { |
2959 | if (!aconnector->mst_port) { | 2962 | sink = create_fake_sink(aconnector); |
2960 | sink = create_fake_sink(aconnector); | 2963 | if (!sink) |
2961 | if (!sink) | 2964 | return stream; |
2962 | return stream; | ||
2963 | } | ||
2964 | } else { | 2965 | } else { |
2965 | sink = aconnector->dc_sink; | 2966 | sink = aconnector->dc_sink; |
2966 | } | 2967 | } |
@@ -3027,9 +3028,6 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, | |||
3027 | 3028 | ||
3028 | update_stream_signal(stream, sink); | 3029 | update_stream_signal(stream, sink); |
3029 | 3030 | ||
3030 | if (dm_state && dm_state->freesync_capable) | ||
3031 | stream->ignore_msa_timing_param = true; | ||
3032 | |||
3033 | finish: | 3031 | finish: |
3034 | if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON) | 3032 | if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON) |
3035 | dc_sink_release(sink); | 3033 | dc_sink_release(sink); |
@@ -4610,12 +4608,6 @@ static void update_freesync_state_on_stream( | |||
4610 | new_crtc_state->base.crtc->base.id, | 4608 | new_crtc_state->base.crtc->base.id, |
4611 | (int)new_crtc_state->base.vrr_enabled, | 4609 | (int)new_crtc_state->base.vrr_enabled, |
4612 | (int)vrr_params.state); | 4610 | (int)vrr_params.state); |
4613 | |||
4614 | if (new_crtc_state->freesync_timing_changed) | ||
4615 | DRM_DEBUG_KMS("VRR timing update: crtc=%u min=%u max=%u\n", | ||
4616 | new_crtc_state->base.crtc->base.id, | ||
4617 | vrr_params.adjust.v_total_min, | ||
4618 | vrr_params.adjust.v_total_max); | ||
4619 | } | 4611 | } |
4620 | 4612 | ||
4621 | static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, | 4613 | static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, |
@@ -4639,7 +4631,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, | |||
4639 | unsigned long flags; | 4631 | unsigned long flags; |
4640 | struct amdgpu_bo *abo; | 4632 | struct amdgpu_bo *abo; |
4641 | uint64_t tiling_flags, dcc_address; | 4633 | uint64_t tiling_flags, dcc_address; |
4642 | struct dc_stream_status *stream_status; | ||
4643 | uint32_t target, target_vblank; | 4634 | uint32_t target, target_vblank; |
4644 | 4635 | ||
4645 | struct { | 4636 | struct { |
@@ -4670,7 +4661,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, | |||
4670 | struct drm_framebuffer *fb = new_plane_state->fb; | 4661 | struct drm_framebuffer *fb = new_plane_state->fb; |
4671 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); | 4662 | struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb); |
4672 | bool pflip_needed; | 4663 | bool pflip_needed; |
4673 | struct dc_plane_state *surface, *dc_plane; | 4664 | struct dc_plane_state *dc_plane; |
4674 | struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); | 4665 | struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state); |
4675 | 4666 | ||
4676 | if (plane->type == DRM_PLANE_TYPE_CURSOR) { | 4667 | if (plane->type == DRM_PLANE_TYPE_CURSOR) { |
@@ -4733,39 +4724,22 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, | |||
4733 | timestamp_ns = ktime_get_ns(); | 4724 | timestamp_ns = ktime_get_ns(); |
4734 | flip->flip_addrs[flip_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000); | 4725 | flip->flip_addrs[flip_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000); |
4735 | flip->surface_updates[flip_count].flip_addr = &flip->flip_addrs[flip_count]; | 4726 | flip->surface_updates[flip_count].flip_addr = &flip->flip_addrs[flip_count]; |
4727 | flip->surface_updates[flip_count].surface = dc_plane; | ||
4736 | 4728 | ||
4737 | stream_status = dc_stream_get_status(acrtc_state->stream); | ||
4738 | if (!stream_status) { | ||
4739 | DRM_ERROR("No stream status for CRTC: id=%d\n", | ||
4740 | acrtc_attach->crtc_id); | ||
4741 | continue; | ||
4742 | } | ||
4743 | |||
4744 | surface = stream_status->plane_states[0]; | ||
4745 | flip->surface_updates[flip_count].surface = surface; | ||
4746 | if (!flip->surface_updates[flip_count].surface) { | 4729 | if (!flip->surface_updates[flip_count].surface) { |
4747 | DRM_ERROR("No surface for CRTC: id=%d\n", | 4730 | DRM_ERROR("No surface for CRTC: id=%d\n", |
4748 | acrtc_attach->crtc_id); | 4731 | acrtc_attach->crtc_id); |
4749 | continue; | 4732 | continue; |
4750 | } | 4733 | } |
4751 | 4734 | ||
4752 | if (acrtc_state->stream) | 4735 | if (plane == pcrtc->primary) |
4753 | update_freesync_state_on_stream( | 4736 | update_freesync_state_on_stream( |
4754 | dm, | 4737 | dm, |
4755 | acrtc_state, | 4738 | acrtc_state, |
4756 | acrtc_state->stream, | 4739 | acrtc_state->stream, |
4757 | surface, | 4740 | dc_plane, |
4758 | flip->flip_addrs[flip_count].flip_timestamp_in_us); | 4741 | flip->flip_addrs[flip_count].flip_timestamp_in_us); |
4759 | 4742 | ||
4760 | /* Update surface timing information. */ | ||
4761 | surface->time.time_elapsed_in_us[surface->time.index] = | ||
4762 | flip->flip_addrs[flip_count].flip_timestamp_in_us - | ||
4763 | surface->time.prev_update_time_in_us; | ||
4764 | surface->time.prev_update_time_in_us = flip->flip_addrs[flip_count].flip_timestamp_in_us; | ||
4765 | surface->time.index++; | ||
4766 | if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX) | ||
4767 | surface->time.index = 0; | ||
4768 | |||
4769 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n", | 4743 | DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n", |
4770 | __func__, | 4744 | __func__, |
4771 | flip->flip_addrs[flip_count].address.grph.addr.high_part, | 4745 | flip->flip_addrs[flip_count].address.grph.addr.high_part, |
@@ -4902,7 +4876,8 @@ cleanup: | |||
4902 | static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_state, | 4876 | static void amdgpu_dm_crtc_copy_transient_flags(struct drm_crtc_state *crtc_state, |
4903 | struct dc_stream_state *stream_state) | 4877 | struct dc_stream_state *stream_state) |
4904 | { | 4878 | { |
4905 | stream_state->mode_changed = crtc_state->mode_changed; | 4879 | stream_state->mode_changed = |
4880 | crtc_state->mode_changed || crtc_state->active_changed; | ||
4906 | } | 4881 | } |
4907 | 4882 | ||
4908 | static int amdgpu_dm_atomic_commit(struct drm_device *dev, | 4883 | static int amdgpu_dm_atomic_commit(struct drm_device *dev, |
@@ -5094,10 +5069,13 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |||
5094 | struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); | 5069 | struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); |
5095 | struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); | 5070 | struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); |
5096 | struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); | 5071 | struct amdgpu_crtc *acrtc = to_amdgpu_crtc(dm_new_con_state->base.crtc); |
5097 | struct dc_surface_update dummy_updates[MAX_SURFACES] = { 0 }; | 5072 | struct dc_surface_update dummy_updates[MAX_SURFACES]; |
5098 | struct dc_stream_update stream_update = { 0 }; | 5073 | struct dc_stream_update stream_update; |
5099 | struct dc_stream_status *status = NULL; | 5074 | struct dc_stream_status *status = NULL; |
5100 | 5075 | ||
5076 | memset(&dummy_updates, 0, sizeof(dummy_updates)); | ||
5077 | memset(&stream_update, 0, sizeof(stream_update)); | ||
5078 | |||
5101 | if (acrtc) { | 5079 | if (acrtc) { |
5102 | new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); | 5080 | new_crtc_state = drm_atomic_get_new_crtc_state(state, &acrtc->base); |
5103 | old_crtc_state = drm_atomic_get_old_crtc_state(state, &acrtc->base); | 5081 | old_crtc_state = drm_atomic_get_old_crtc_state(state, &acrtc->base); |
@@ -5174,9 +5152,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) | |||
5174 | 5152 | ||
5175 | manage_dm_interrupts(adev, acrtc, true); | 5153 | manage_dm_interrupts(adev, acrtc, true); |
5176 | 5154 | ||
5155 | #ifdef CONFIG_DEBUG_FS | ||
5177 | /* The stream has changed so CRC capture needs to re-enabled. */ | 5156 | /* The stream has changed so CRC capture needs to re-enabled. */ |
5178 | if (dm_new_crtc_state->crc_enabled) | 5157 | if (dm_new_crtc_state->crc_enabled) |
5179 | amdgpu_dm_crtc_set_crc_source(crtc, "auto"); | 5158 | amdgpu_dm_crtc_set_crc_source(crtc, "auto"); |
5159 | #endif | ||
5180 | } | 5160 | } |
5181 | 5161 | ||
5182 | /* update planes when needed per crtc*/ | 5162 | /* update planes when needed per crtc*/ |
@@ -5372,10 +5352,13 @@ static void get_freesync_config_for_crtc( | |||
5372 | struct mod_freesync_config config = {0}; | 5352 | struct mod_freesync_config config = {0}; |
5373 | struct amdgpu_dm_connector *aconnector = | 5353 | struct amdgpu_dm_connector *aconnector = |
5374 | to_amdgpu_dm_connector(new_con_state->base.connector); | 5354 | to_amdgpu_dm_connector(new_con_state->base.connector); |
5355 | struct drm_display_mode *mode = &new_crtc_state->base.mode; | ||
5375 | 5356 | ||
5376 | new_crtc_state->vrr_supported = new_con_state->freesync_capable; | 5357 | new_crtc_state->vrr_supported = new_con_state->freesync_capable && |
5358 | aconnector->min_vfreq <= drm_mode_vrefresh(mode); | ||
5377 | 5359 | ||
5378 | if (new_con_state->freesync_capable) { | 5360 | if (new_crtc_state->vrr_supported) { |
5361 | new_crtc_state->stream->ignore_msa_timing_param = true; | ||
5379 | config.state = new_crtc_state->base.vrr_enabled ? | 5362 | config.state = new_crtc_state->base.vrr_enabled ? |
5380 | VRR_STATE_ACTIVE_VARIABLE : | 5363 | VRR_STATE_ACTIVE_VARIABLE : |
5381 | VRR_STATE_INACTIVE; | 5364 | VRR_STATE_INACTIVE; |
@@ -5783,7 +5766,6 @@ dm_determine_update_type_for_commit(struct dc *dc, | |||
5783 | 5766 | ||
5784 | struct dc_surface_update *updates; | 5767 | struct dc_surface_update *updates; |
5785 | struct dc_plane_state *surface; | 5768 | struct dc_plane_state *surface; |
5786 | struct dc_stream_update stream_update; | ||
5787 | enum surface_update_type update_type = UPDATE_TYPE_FAST; | 5769 | enum surface_update_type update_type = UPDATE_TYPE_FAST; |
5788 | 5770 | ||
5789 | updates = kcalloc(MAX_SURFACES, sizeof(*updates), GFP_KERNEL); | 5771 | updates = kcalloc(MAX_SURFACES, sizeof(*updates), GFP_KERNEL); |
@@ -5797,79 +5779,85 @@ dm_determine_update_type_for_commit(struct dc *dc, | |||
5797 | } | 5779 | } |
5798 | 5780 | ||
5799 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { | 5781 | for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { |
5782 | struct dc_stream_update stream_update = { 0 }; | ||
5783 | |||
5800 | new_dm_crtc_state = to_dm_crtc_state(new_crtc_state); | 5784 | new_dm_crtc_state = to_dm_crtc_state(new_crtc_state); |
5801 | old_dm_crtc_state = to_dm_crtc_state(old_crtc_state); | 5785 | old_dm_crtc_state = to_dm_crtc_state(old_crtc_state); |
5802 | num_plane = 0; | 5786 | num_plane = 0; |
5803 | 5787 | ||
5804 | if (new_dm_crtc_state->stream) { | 5788 | if (!new_dm_crtc_state->stream) { |
5805 | 5789 | if (!new_dm_crtc_state->stream && old_dm_crtc_state->stream) { | |
5806 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { | 5790 | update_type = UPDATE_TYPE_FULL; |
5807 | new_plane_crtc = new_plane_state->crtc; | 5791 | goto cleanup; |
5808 | old_plane_crtc = old_plane_state->crtc; | ||
5809 | new_dm_plane_state = to_dm_plane_state(new_plane_state); | ||
5810 | old_dm_plane_state = to_dm_plane_state(old_plane_state); | ||
5811 | |||
5812 | if (plane->type == DRM_PLANE_TYPE_CURSOR) | ||
5813 | continue; | ||
5814 | |||
5815 | if (!state->allow_modeset) | ||
5816 | continue; | ||
5817 | |||
5818 | if (crtc == new_plane_crtc) { | ||
5819 | updates[num_plane].surface = &surface[num_plane]; | ||
5820 | |||
5821 | if (new_crtc_state->mode_changed) { | ||
5822 | updates[num_plane].surface->src_rect = | ||
5823 | new_dm_plane_state->dc_state->src_rect; | ||
5824 | updates[num_plane].surface->dst_rect = | ||
5825 | new_dm_plane_state->dc_state->dst_rect; | ||
5826 | updates[num_plane].surface->rotation = | ||
5827 | new_dm_plane_state->dc_state->rotation; | ||
5828 | updates[num_plane].surface->in_transfer_func = | ||
5829 | new_dm_plane_state->dc_state->in_transfer_func; | ||
5830 | stream_update.dst = new_dm_crtc_state->stream->dst; | ||
5831 | stream_update.src = new_dm_crtc_state->stream->src; | ||
5832 | } | ||
5833 | |||
5834 | if (new_crtc_state->color_mgmt_changed) { | ||
5835 | updates[num_plane].gamma = | ||
5836 | new_dm_plane_state->dc_state->gamma_correction; | ||
5837 | updates[num_plane].in_transfer_func = | ||
5838 | new_dm_plane_state->dc_state->in_transfer_func; | ||
5839 | stream_update.gamut_remap = | ||
5840 | &new_dm_crtc_state->stream->gamut_remap_matrix; | ||
5841 | stream_update.out_transfer_func = | ||
5842 | new_dm_crtc_state->stream->out_transfer_func; | ||
5843 | } | ||
5844 | |||
5845 | num_plane++; | ||
5846 | } | ||
5847 | } | 5792 | } |
5848 | 5793 | ||
5849 | if (num_plane > 0) { | 5794 | continue; |
5850 | ret = dm_atomic_get_state(state, &dm_state); | 5795 | } |
5851 | if (ret) | ||
5852 | goto cleanup; | ||
5853 | 5796 | ||
5854 | old_dm_state = dm_atomic_get_old_state(state); | 5797 | for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { |
5855 | if (!old_dm_state) { | 5798 | new_plane_crtc = new_plane_state->crtc; |
5856 | ret = -EINVAL; | 5799 | old_plane_crtc = old_plane_state->crtc; |
5857 | goto cleanup; | 5800 | new_dm_plane_state = to_dm_plane_state(new_plane_state); |
5858 | } | 5801 | old_dm_plane_state = to_dm_plane_state(old_plane_state); |
5859 | 5802 | ||
5860 | status = dc_stream_get_status_from_state(old_dm_state->context, | 5803 | if (plane->type == DRM_PLANE_TYPE_CURSOR) |
5861 | new_dm_crtc_state->stream); | 5804 | continue; |
5862 | 5805 | ||
5863 | update_type = dc_check_update_surfaces_for_stream(dc, updates, num_plane, | 5806 | if (!state->allow_modeset) |
5864 | &stream_update, status); | 5807 | continue; |
5865 | 5808 | ||
5866 | if (update_type > UPDATE_TYPE_MED) { | 5809 | if (crtc != new_plane_crtc) |
5867 | update_type = UPDATE_TYPE_FULL; | 5810 | continue; |
5868 | goto cleanup; | 5811 | |
5869 | } | 5812 | updates[num_plane].surface = &surface[num_plane]; |
5813 | |||
5814 | if (new_crtc_state->mode_changed) { | ||
5815 | updates[num_plane].surface->src_rect = | ||
5816 | new_dm_plane_state->dc_state->src_rect; | ||
5817 | updates[num_plane].surface->dst_rect = | ||
5818 | new_dm_plane_state->dc_state->dst_rect; | ||
5819 | updates[num_plane].surface->rotation = | ||
5820 | new_dm_plane_state->dc_state->rotation; | ||
5821 | updates[num_plane].surface->in_transfer_func = | ||
5822 | new_dm_plane_state->dc_state->in_transfer_func; | ||
5823 | stream_update.dst = new_dm_crtc_state->stream->dst; | ||
5824 | stream_update.src = new_dm_crtc_state->stream->src; | ||
5825 | } | ||
5826 | |||
5827 | if (new_crtc_state->color_mgmt_changed) { | ||
5828 | updates[num_plane].gamma = | ||
5829 | new_dm_plane_state->dc_state->gamma_correction; | ||
5830 | updates[num_plane].in_transfer_func = | ||
5831 | new_dm_plane_state->dc_state->in_transfer_func; | ||
5832 | stream_update.gamut_remap = | ||
5833 | &new_dm_crtc_state->stream->gamut_remap_matrix; | ||
5834 | stream_update.out_transfer_func = | ||
5835 | new_dm_crtc_state->stream->out_transfer_func; | ||
5870 | } | 5836 | } |
5871 | 5837 | ||
5872 | } else if (!new_dm_crtc_state->stream && old_dm_crtc_state->stream) { | 5838 | num_plane++; |
5839 | } | ||
5840 | |||
5841 | if (num_plane == 0) | ||
5842 | continue; | ||
5843 | |||
5844 | ret = dm_atomic_get_state(state, &dm_state); | ||
5845 | if (ret) | ||
5846 | goto cleanup; | ||
5847 | |||
5848 | old_dm_state = dm_atomic_get_old_state(state); | ||
5849 | if (!old_dm_state) { | ||
5850 | ret = -EINVAL; | ||
5851 | goto cleanup; | ||
5852 | } | ||
5853 | |||
5854 | status = dc_stream_get_status_from_state(old_dm_state->context, | ||
5855 | new_dm_crtc_state->stream); | ||
5856 | |||
5857 | update_type = dc_check_update_surfaces_for_stream(dc, updates, num_plane, | ||
5858 | &stream_update, status); | ||
5859 | |||
5860 | if (update_type > UPDATE_TYPE_MED) { | ||
5873 | update_type = UPDATE_TYPE_FULL; | 5861 | update_type = UPDATE_TYPE_FULL; |
5874 | goto cleanup; | 5862 | goto cleanup; |
5875 | } | 5863 | } |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 748d6ff3e4f3..f51d52eb52e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | |||
@@ -174,6 +174,11 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) | |||
174 | aconnector->edid = edid; | 174 | aconnector->edid = edid; |
175 | } | 175 | } |
176 | 176 | ||
177 | if (aconnector->dc_sink && aconnector->dc_sink->sink_signal == SIGNAL_TYPE_VIRTUAL) { | ||
178 | dc_sink_release(aconnector->dc_sink); | ||
179 | aconnector->dc_sink = NULL; | ||
180 | } | ||
181 | |||
177 | if (!aconnector->dc_sink) { | 182 | if (!aconnector->dc_sink) { |
178 | struct dc_sink *dc_sink; | 183 | struct dc_sink *dc_sink; |
179 | struct dc_sink_init_data init_params = { | 184 | struct dc_sink_init_data init_params = { |
diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c index 7d102ac0d61b..1ef0074302c5 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c +++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c | |||
@@ -63,7 +63,7 @@ void scaler_settings_calculation(struct dcn_bw_internal_vars *v) | |||
63 | if (v->interlace_output[k] == 1.0) { | 63 | if (v->interlace_output[k] == 1.0) { |
64 | v->v_ratio[k] = 2.0 * v->v_ratio[k]; | 64 | v->v_ratio[k] = 2.0 * v->v_ratio[k]; |
65 | } | 65 | } |
66 | if ((v->underscan_output[k] == 1.0)) { | 66 | if (v->underscan_output[k] == 1.0) { |
67 | v->h_ratio[k] = v->h_ratio[k] * v->under_scan_factor; | 67 | v->h_ratio[k] = v->h_ratio[k] * v->under_scan_factor; |
68 | v->v_ratio[k] = v->v_ratio[k] * v->under_scan_factor; | 68 | v->v_ratio[k] = v->v_ratio[k] * v->under_scan_factor; |
69 | } | 69 | } |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e22be0aefd1b..52f838442e21 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c | |||
@@ -621,7 +621,6 @@ static bool construct(struct dc *dc, | |||
621 | #endif | 621 | #endif |
622 | 622 | ||
623 | enum dce_version dc_version = DCE_VERSION_UNKNOWN; | 623 | enum dce_version dc_version = DCE_VERSION_UNKNOWN; |
624 | |||
625 | dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL); | 624 | dc_dceip = kzalloc(sizeof(*dc_dceip), GFP_KERNEL); |
626 | if (!dc_dceip) { | 625 | if (!dc_dceip) { |
627 | dm_error("%s: failed to create dceip\n", __func__); | 626 | dm_error("%s: failed to create dceip\n", __func__); |
@@ -869,8 +868,9 @@ static void program_timing_sync( | |||
869 | struct dc *dc, | 868 | struct dc *dc, |
870 | struct dc_state *ctx) | 869 | struct dc_state *ctx) |
871 | { | 870 | { |
872 | int i, j; | 871 | int i, j, k; |
873 | int group_index = 0; | 872 | int group_index = 0; |
873 | int num_group = 0; | ||
874 | int pipe_count = dc->res_pool->pipe_count; | 874 | int pipe_count = dc->res_pool->pipe_count; |
875 | struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; | 875 | struct pipe_ctx *unsynced_pipes[MAX_PIPES] = { NULL }; |
876 | 876 | ||
@@ -907,11 +907,11 @@ static void program_timing_sync( | |||
907 | } | 907 | } |
908 | } | 908 | } |
909 | 909 | ||
910 | /* set first unblanked pipe as master */ | 910 | /* set first pipe with plane as master */ |
911 | for (j = 0; j < group_size; j++) { | 911 | for (j = 0; j < group_size; j++) { |
912 | struct pipe_ctx *temp; | 912 | struct pipe_ctx *temp; |
913 | 913 | ||
914 | if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { | 914 | if (pipe_set[j]->plane_state) { |
915 | if (j == 0) | 915 | if (j == 0) |
916 | break; | 916 | break; |
917 | 917 | ||
@@ -922,9 +922,21 @@ static void program_timing_sync( | |||
922 | } | 922 | } |
923 | } | 923 | } |
924 | 924 | ||
925 | /* remove any other unblanked pipes as they have already been synced */ | 925 | |
926 | for (k = 0; k < group_size; k++) { | ||
927 | struct dc_stream_status *status = dc_stream_get_status_from_state(ctx, pipe_set[k]->stream); | ||
928 | |||
929 | status->timing_sync_info.group_id = num_group; | ||
930 | status->timing_sync_info.group_size = group_size; | ||
931 | if (k == 0) | ||
932 | status->timing_sync_info.master = true; | ||
933 | else | ||
934 | status->timing_sync_info.master = false; | ||
935 | |||
936 | } | ||
937 | /* remove any other pipes with plane as they have already been synced */ | ||
926 | for (j = j + 1; j < group_size; j++) { | 938 | for (j = j + 1; j < group_size; j++) { |
927 | if (pipe_set[j]->stream_res.tg->funcs->is_blanked && !pipe_set[j]->stream_res.tg->funcs->is_blanked(pipe_set[j]->stream_res.tg)) { | 939 | if (pipe_set[j]->plane_state) { |
928 | group_size--; | 940 | group_size--; |
929 | pipe_set[j] = pipe_set[group_size]; | 941 | pipe_set[j] = pipe_set[group_size]; |
930 | j--; | 942 | j--; |
@@ -936,6 +948,7 @@ static void program_timing_sync( | |||
936 | dc, group_index, group_size, pipe_set); | 948 | dc, group_index, group_size, pipe_set); |
937 | group_index++; | 949 | group_index++; |
938 | } | 950 | } |
951 | num_group++; | ||
939 | } | 952 | } |
940 | } | 953 | } |
941 | 954 | ||
@@ -956,6 +969,52 @@ static bool context_changed( | |||
956 | return false; | 969 | return false; |
957 | } | 970 | } |
958 | 971 | ||
972 | bool dc_validate_seamless_boot_timing(struct dc *dc, | ||
973 | const struct dc_sink *sink, | ||
974 | struct dc_crtc_timing *crtc_timing) | ||
975 | { | ||
976 | struct timing_generator *tg; | ||
977 | struct dc_link *link = sink->link; | ||
978 | unsigned int inst; | ||
979 | |||
980 | /* Check for enabled DIG to identify enabled display */ | ||
981 | if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) | ||
982 | return false; | ||
983 | |||
984 | /* Check for which front end is used by this encoder. | ||
985 | * Note the inst is 1 indexed, where 0 is undefined. | ||
986 | * Note that DIG_FE can source from different OTG but our | ||
987 | * current implementation always map 1-to-1, so this code makes | ||
988 | * the same assumption and doesn't check OTG source. | ||
989 | */ | ||
990 | inst = link->link_enc->funcs->get_dig_frontend(link->link_enc) - 1; | ||
991 | |||
992 | /* Instance should be within the range of the pool */ | ||
993 | if (inst >= dc->res_pool->pipe_count) | ||
994 | return false; | ||
995 | |||
996 | tg = dc->res_pool->timing_generators[inst]; | ||
997 | |||
998 | if (!tg->funcs->is_matching_timing) | ||
999 | return false; | ||
1000 | |||
1001 | if (!tg->funcs->is_matching_timing(tg, crtc_timing)) | ||
1002 | return false; | ||
1003 | |||
1004 | if (dc_is_dp_signal(link->connector_signal)) { | ||
1005 | unsigned int pix_clk_100hz; | ||
1006 | |||
1007 | dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz( | ||
1008 | dc->res_pool->dp_clock_source, | ||
1009 | inst, &pix_clk_100hz); | ||
1010 | |||
1011 | if (crtc_timing->pix_clk_100hz != pix_clk_100hz) | ||
1012 | return false; | ||
1013 | } | ||
1014 | |||
1015 | return true; | ||
1016 | } | ||
1017 | |||
959 | bool dc_enable_stereo( | 1018 | bool dc_enable_stereo( |
960 | struct dc *dc, | 1019 | struct dc *dc, |
961 | struct dc_state *context, | 1020 | struct dc_state *context, |
@@ -1037,6 +1096,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c | |||
1037 | const struct dc_link *link = context->streams[i]->link; | 1096 | const struct dc_link *link = context->streams[i]->link; |
1038 | struct dc_stream_status *status; | 1097 | struct dc_stream_status *status; |
1039 | 1098 | ||
1099 | if (context->streams[i]->apply_seamless_boot_optimization) | ||
1100 | context->streams[i]->apply_seamless_boot_optimization = false; | ||
1101 | |||
1040 | if (!context->streams[i]->mode_changed) | 1102 | if (!context->streams[i]->mode_changed) |
1041 | continue; | 1103 | continue; |
1042 | 1104 | ||
@@ -1112,6 +1174,9 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) | |||
1112 | int i; | 1174 | int i; |
1113 | struct dc_state *context = dc->current_state; | 1175 | struct dc_state *context = dc->current_state; |
1114 | 1176 | ||
1177 | if (dc->optimized_required == false) | ||
1178 | return true; | ||
1179 | |||
1115 | post_surface_trace(dc); | 1180 | post_surface_trace(dc); |
1116 | 1181 | ||
1117 | for (i = 0; i < dc->res_pool->pipe_count; i++) | 1182 | for (i = 0; i < dc->res_pool->pipe_count; i++) |
@@ -1440,6 +1505,101 @@ static struct dc_stream_status *stream_get_status( | |||
1440 | 1505 | ||
1441 | static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; | 1506 | static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; |
1442 | 1507 | ||
1508 | static void copy_surface_update_to_plane( | ||
1509 | struct dc_plane_state *surface, | ||
1510 | struct dc_surface_update *srf_update) | ||
1511 | { | ||
1512 | if (srf_update->flip_addr) { | ||
1513 | surface->address = srf_update->flip_addr->address; | ||
1514 | surface->flip_immediate = | ||
1515 | srf_update->flip_addr->flip_immediate; | ||
1516 | surface->time.time_elapsed_in_us[surface->time.index] = | ||
1517 | srf_update->flip_addr->flip_timestamp_in_us - | ||
1518 | surface->time.prev_update_time_in_us; | ||
1519 | surface->time.prev_update_time_in_us = | ||
1520 | srf_update->flip_addr->flip_timestamp_in_us; | ||
1521 | surface->time.index++; | ||
1522 | if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX) | ||
1523 | surface->time.index = 0; | ||
1524 | } | ||
1525 | |||
1526 | if (srf_update->scaling_info) { | ||
1527 | surface->scaling_quality = | ||
1528 | srf_update->scaling_info->scaling_quality; | ||
1529 | surface->dst_rect = | ||
1530 | srf_update->scaling_info->dst_rect; | ||
1531 | surface->src_rect = | ||
1532 | srf_update->scaling_info->src_rect; | ||
1533 | surface->clip_rect = | ||
1534 | srf_update->scaling_info->clip_rect; | ||
1535 | } | ||
1536 | |||
1537 | if (srf_update->plane_info) { | ||
1538 | surface->color_space = | ||
1539 | srf_update->plane_info->color_space; | ||
1540 | surface->format = | ||
1541 | srf_update->plane_info->format; | ||
1542 | surface->plane_size = | ||
1543 | srf_update->plane_info->plane_size; | ||
1544 | surface->rotation = | ||
1545 | srf_update->plane_info->rotation; | ||
1546 | surface->horizontal_mirror = | ||
1547 | srf_update->plane_info->horizontal_mirror; | ||
1548 | surface->stereo_format = | ||
1549 | srf_update->plane_info->stereo_format; | ||
1550 | surface->tiling_info = | ||
1551 | srf_update->plane_info->tiling_info; | ||
1552 | surface->visible = | ||
1553 | srf_update->plane_info->visible; | ||
1554 | surface->per_pixel_alpha = | ||
1555 | srf_update->plane_info->per_pixel_alpha; | ||
1556 | surface->global_alpha = | ||
1557 | srf_update->plane_info->global_alpha; | ||
1558 | surface->global_alpha_value = | ||
1559 | srf_update->plane_info->global_alpha_value; | ||
1560 | surface->dcc = | ||
1561 | srf_update->plane_info->dcc; | ||
1562 | surface->sdr_white_level = | ||
1563 | srf_update->plane_info->sdr_white_level; | ||
1564 | } | ||
1565 | |||
1566 | if (srf_update->gamma && | ||
1567 | (surface->gamma_correction != | ||
1568 | srf_update->gamma)) { | ||
1569 | memcpy(&surface->gamma_correction->entries, | ||
1570 | &srf_update->gamma->entries, | ||
1571 | sizeof(struct dc_gamma_entries)); | ||
1572 | surface->gamma_correction->is_identity = | ||
1573 | srf_update->gamma->is_identity; | ||
1574 | surface->gamma_correction->num_entries = | ||
1575 | srf_update->gamma->num_entries; | ||
1576 | surface->gamma_correction->type = | ||
1577 | srf_update->gamma->type; | ||
1578 | } | ||
1579 | |||
1580 | if (srf_update->in_transfer_func && | ||
1581 | (surface->in_transfer_func != | ||
1582 | srf_update->in_transfer_func)) { | ||
1583 | surface->in_transfer_func->sdr_ref_white_level = | ||
1584 | srf_update->in_transfer_func->sdr_ref_white_level; | ||
1585 | surface->in_transfer_func->tf = | ||
1586 | srf_update->in_transfer_func->tf; | ||
1587 | surface->in_transfer_func->type = | ||
1588 | srf_update->in_transfer_func->type; | ||
1589 | memcpy(&surface->in_transfer_func->tf_pts, | ||
1590 | &srf_update->in_transfer_func->tf_pts, | ||
1591 | sizeof(struct dc_transfer_func_distributed_points)); | ||
1592 | } | ||
1593 | |||
1594 | if (srf_update->input_csc_color_matrix) | ||
1595 | surface->input_csc_color_matrix = | ||
1596 | *srf_update->input_csc_color_matrix; | ||
1597 | |||
1598 | if (srf_update->coeff_reduction_factor) | ||
1599 | surface->coeff_reduction_factor = | ||
1600 | *srf_update->coeff_reduction_factor; | ||
1601 | } | ||
1602 | |||
1443 | static void commit_planes_do_stream_update(struct dc *dc, | 1603 | static void commit_planes_do_stream_update(struct dc *dc, |
1444 | struct dc_stream_state *stream, | 1604 | struct dc_stream_state *stream, |
1445 | struct dc_stream_update *stream_update, | 1605 | struct dc_stream_update *stream_update, |
@@ -1463,13 +1623,13 @@ static void commit_planes_do_stream_update(struct dc *dc, | |||
1463 | stream_update->adjust->v_total_min, | 1623 | stream_update->adjust->v_total_min, |
1464 | stream_update->adjust->v_total_max); | 1624 | stream_update->adjust->v_total_max); |
1465 | 1625 | ||
1466 | if (stream_update->vline0_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt) | 1626 | if (stream_update->periodic_vsync_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt) |
1467 | pipe_ctx->stream_res.tg->funcs->program_vline_interrupt( | 1627 | pipe_ctx->stream_res.tg->funcs->program_vline_interrupt( |
1468 | pipe_ctx->stream_res.tg, VLINE0, stream->vline0_config); | 1628 | pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, VLINE0, &stream->periodic_vsync_config); |
1469 | 1629 | ||
1470 | if (stream_update->vline1_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt) | 1630 | if (stream_update->enhanced_sync_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt) |
1471 | pipe_ctx->stream_res.tg->funcs->program_vline_interrupt( | 1631 | pipe_ctx->stream_res.tg->funcs->program_vline_interrupt( |
1472 | pipe_ctx->stream_res.tg, VLINE1, stream->vline1_config); | 1632 | pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, VLINE1, &stream->enhanced_sync_config); |
1473 | 1633 | ||
1474 | if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || | 1634 | if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || |
1475 | stream_update->vrr_infopacket || | 1635 | stream_update->vrr_infopacket || |
@@ -1645,14 +1805,7 @@ void dc_commit_updates_for_stream(struct dc *dc, | |||
1645 | for (i = 0; i < surface_count; i++) { | 1805 | for (i = 0; i < surface_count; i++) { |
1646 | struct dc_plane_state *surface = srf_updates[i].surface; | 1806 | struct dc_plane_state *surface = srf_updates[i].surface; |
1647 | 1807 | ||
1648 | /* TODO: On flip we don't build the state, so it still has the | 1808 | copy_surface_update_to_plane(surface, &srf_updates[i]); |
1649 | * old address. Which is why we are updating the address here | ||
1650 | */ | ||
1651 | if (srf_updates[i].flip_addr) { | ||
1652 | surface->address = srf_updates[i].flip_addr->address; | ||
1653 | surface->flip_immediate = srf_updates[i].flip_addr->flip_immediate; | ||
1654 | |||
1655 | } | ||
1656 | 1809 | ||
1657 | if (update_type >= UPDATE_TYPE_MED) { | 1810 | if (update_type >= UPDATE_TYPE_MED) { |
1658 | for (j = 0; j < dc->res_pool->pipe_count; j++) { | 1811 | for (j = 0; j < dc->res_pool->pipe_count; j++) { |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 8ff5d42587c2..7f5a947ad31d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c | |||
@@ -76,6 +76,12 @@ static void destruct(struct dc_link *link) | |||
76 | { | 76 | { |
77 | int i; | 77 | int i; |
78 | 78 | ||
79 | if (link->hpd_gpio != NULL) { | ||
80 | dal_gpio_close(link->hpd_gpio); | ||
81 | dal_gpio_destroy_irq(&link->hpd_gpio); | ||
82 | link->hpd_gpio = NULL; | ||
83 | } | ||
84 | |||
79 | if (link->ddc) | 85 | if (link->ddc) |
80 | dal_ddc_service_destroy(&link->ddc); | 86 | dal_ddc_service_destroy(&link->ddc); |
81 | 87 | ||
@@ -931,18 +937,11 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason) | |||
931 | 937 | ||
932 | bool dc_link_get_hpd_state(struct dc_link *dc_link) | 938 | bool dc_link_get_hpd_state(struct dc_link *dc_link) |
933 | { | 939 | { |
934 | struct gpio *hpd_pin; | ||
935 | uint32_t state; | 940 | uint32_t state; |
936 | 941 | ||
937 | hpd_pin = get_hpd_gpio(dc_link->ctx->dc_bios, | 942 | dal_gpio_lock_pin(dc_link->hpd_gpio); |
938 | dc_link->link_id, dc_link->ctx->gpio_service); | 943 | dal_gpio_get_value(dc_link->hpd_gpio, &state); |
939 | if (hpd_pin == NULL) | 944 | dal_gpio_unlock_pin(dc_link->hpd_gpio); |
940 | ASSERT(false); | ||
941 | |||
942 | dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT); | ||
943 | dal_gpio_get_value(hpd_pin, &state); | ||
944 | dal_gpio_close(hpd_pin); | ||
945 | dal_gpio_destroy_irq(&hpd_pin); | ||
946 | 945 | ||
947 | return state; | 946 | return state; |
948 | } | 947 | } |
@@ -1098,7 +1097,6 @@ static bool construct( | |||
1098 | const struct link_init_data *init_params) | 1097 | const struct link_init_data *init_params) |
1099 | { | 1098 | { |
1100 | uint8_t i; | 1099 | uint8_t i; |
1101 | struct gpio *hpd_gpio = NULL; | ||
1102 | struct ddc_service_init_data ddc_service_init_data = { { 0 } }; | 1100 | struct ddc_service_init_data ddc_service_init_data = { { 0 } }; |
1103 | struct dc_context *dc_ctx = init_params->ctx; | 1101 | struct dc_context *dc_ctx = init_params->ctx; |
1104 | struct encoder_init_data enc_init_data = { 0 }; | 1102 | struct encoder_init_data enc_init_data = { 0 }; |
@@ -1128,10 +1126,12 @@ static bool construct( | |||
1128 | if (link->dc->res_pool->funcs->link_init) | 1126 | if (link->dc->res_pool->funcs->link_init) |
1129 | link->dc->res_pool->funcs->link_init(link); | 1127 | link->dc->res_pool->funcs->link_init(link); |
1130 | 1128 | ||
1131 | hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); | 1129 | link->hpd_gpio = get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service); |
1132 | 1130 | if (link->hpd_gpio != NULL) { | |
1133 | if (hpd_gpio != NULL) | 1131 | dal_gpio_open(link->hpd_gpio, GPIO_MODE_INTERRUPT); |
1134 | link->irq_source_hpd = dal_irq_get_source(hpd_gpio); | 1132 | dal_gpio_unlock_pin(link->hpd_gpio); |
1133 | link->irq_source_hpd = dal_irq_get_source(link->hpd_gpio); | ||
1134 | } | ||
1135 | 1135 | ||
1136 | switch (link->link_id.id) { | 1136 | switch (link->link_id.id) { |
1137 | case CONNECTOR_ID_HDMI_TYPE_A: | 1137 | case CONNECTOR_ID_HDMI_TYPE_A: |
@@ -1149,18 +1149,18 @@ static bool construct( | |||
1149 | case CONNECTOR_ID_DISPLAY_PORT: | 1149 | case CONNECTOR_ID_DISPLAY_PORT: |
1150 | link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; | 1150 | link->connector_signal = SIGNAL_TYPE_DISPLAY_PORT; |
1151 | 1151 | ||
1152 | if (hpd_gpio != NULL) | 1152 | if (link->hpd_gpio != NULL) |
1153 | link->irq_source_hpd_rx = | 1153 | link->irq_source_hpd_rx = |
1154 | dal_irq_get_rx_source(hpd_gpio); | 1154 | dal_irq_get_rx_source(link->hpd_gpio); |
1155 | 1155 | ||
1156 | break; | 1156 | break; |
1157 | case CONNECTOR_ID_EDP: | 1157 | case CONNECTOR_ID_EDP: |
1158 | link->connector_signal = SIGNAL_TYPE_EDP; | 1158 | link->connector_signal = SIGNAL_TYPE_EDP; |
1159 | 1159 | ||
1160 | if (hpd_gpio != NULL) { | 1160 | if (link->hpd_gpio != NULL) { |
1161 | link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; | 1161 | link->irq_source_hpd = DC_IRQ_SOURCE_INVALID; |
1162 | link->irq_source_hpd_rx = | 1162 | link->irq_source_hpd_rx = |
1163 | dal_irq_get_rx_source(hpd_gpio); | 1163 | dal_irq_get_rx_source(link->hpd_gpio); |
1164 | } | 1164 | } |
1165 | break; | 1165 | break; |
1166 | case CONNECTOR_ID_LVDS: | 1166 | case CONNECTOR_ID_LVDS: |
@@ -1171,10 +1171,7 @@ static bool construct( | |||
1171 | goto create_fail; | 1171 | goto create_fail; |
1172 | } | 1172 | } |
1173 | 1173 | ||
1174 | if (hpd_gpio != NULL) { | 1174 | |
1175 | dal_gpio_destroy_irq(&hpd_gpio); | ||
1176 | hpd_gpio = NULL; | ||
1177 | } | ||
1178 | 1175 | ||
1179 | /* TODO: #DAL3 Implement id to str function.*/ | 1176 | /* TODO: #DAL3 Implement id to str function.*/ |
1180 | LINK_INFO("Connector[%d] description:" | 1177 | LINK_INFO("Connector[%d] description:" |
@@ -1277,8 +1274,9 @@ link_enc_create_fail: | |||
1277 | ddc_create_fail: | 1274 | ddc_create_fail: |
1278 | create_fail: | 1275 | create_fail: |
1279 | 1276 | ||
1280 | if (hpd_gpio != NULL) { | 1277 | if (link->hpd_gpio != NULL) { |
1281 | dal_gpio_destroy_irq(&hpd_gpio); | 1278 | dal_gpio_destroy_irq(&link->hpd_gpio); |
1279 | link->hpd_gpio = NULL; | ||
1282 | } | 1280 | } |
1283 | 1281 | ||
1284 | return false; | 1282 | return false; |
@@ -2582,13 +2580,23 @@ void core_link_enable_stream( | |||
2582 | &stream->timing); | 2580 | &stream->timing); |
2583 | 2581 | ||
2584 | if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { | 2582 | if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)) { |
2583 | bool apply_edp_fast_boot_optimization = | ||
2584 | pipe_ctx->stream->apply_edp_fast_boot_optimization; | ||
2585 | |||
2586 | pipe_ctx->stream->apply_edp_fast_boot_optimization = false; | ||
2587 | |||
2585 | resource_build_info_frame(pipe_ctx); | 2588 | resource_build_info_frame(pipe_ctx); |
2586 | core_dc->hwss.update_info_frame(pipe_ctx); | 2589 | core_dc->hwss.update_info_frame(pipe_ctx); |
2587 | 2590 | ||
2591 | /* Do not touch link on seamless boot optimization. */ | ||
2592 | if (pipe_ctx->stream->apply_seamless_boot_optimization) { | ||
2593 | pipe_ctx->stream->dpms_off = false; | ||
2594 | return; | ||
2595 | } | ||
2596 | |||
2588 | /* eDP lit up by bios already, no need to enable again. */ | 2597 | /* eDP lit up by bios already, no need to enable again. */ |
2589 | if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP && | 2598 | if (pipe_ctx->stream->signal == SIGNAL_TYPE_EDP && |
2590 | pipe_ctx->stream->apply_edp_fast_boot_optimization) { | 2599 | apply_edp_fast_boot_optimization) { |
2591 | pipe_ctx->stream->apply_edp_fast_boot_optimization = false; | ||
2592 | pipe_ctx->stream->dpms_off = false; | 2600 | pipe_ctx->stream->dpms_off = false; |
2593 | return; | 2601 | return; |
2594 | } | 2602 | } |
@@ -2615,6 +2623,8 @@ void core_link_enable_stream( | |||
2615 | } | 2623 | } |
2616 | } | 2624 | } |
2617 | 2625 | ||
2626 | stream->link->link_status.link_active = true; | ||
2627 | |||
2618 | core_dc->hwss.enable_audio_stream(pipe_ctx); | 2628 | core_dc->hwss.enable_audio_stream(pipe_ctx); |
2619 | 2629 | ||
2620 | /* turn off otg test pattern if enable */ | 2630 | /* turn off otg test pattern if enable */ |
@@ -2649,6 +2659,8 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) | |||
2649 | core_dc->hwss.disable_stream(pipe_ctx, option); | 2659 | core_dc->hwss.disable_stream(pipe_ctx, option); |
2650 | 2660 | ||
2651 | disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); | 2661 | disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); |
2662 | |||
2663 | pipe_ctx->stream->link->link_status.link_active = false; | ||
2652 | } | 2664 | } |
2653 | 2665 | ||
2654 | void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) | 2666 | void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 92f565ca1260..09d301216076 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | |||
@@ -47,7 +47,9 @@ static void wait_for_training_aux_rd_interval( | |||
47 | struct dc_link *link, | 47 | struct dc_link *link, |
48 | uint32_t default_wait_in_micro_secs) | 48 | uint32_t default_wait_in_micro_secs) |
49 | { | 49 | { |
50 | union training_aux_rd_interval training_rd_interval = {0}; | 50 | union training_aux_rd_interval training_rd_interval; |
51 | |||
52 | memset(&training_rd_interval, 0, sizeof(training_rd_interval)); | ||
51 | 53 | ||
52 | /* overwrite the delay if rev > 1.1*/ | 54 | /* overwrite the delay if rev > 1.1*/ |
53 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { | 55 | if (link->dpcd_caps.dpcd_rev.raw >= DPCD_REV_12) { |
@@ -2538,7 +2540,6 @@ void detect_edp_sink_caps(struct dc_link *link) | |||
2538 | uint32_t entry; | 2540 | uint32_t entry; |
2539 | uint32_t link_rate_in_khz; | 2541 | uint32_t link_rate_in_khz; |
2540 | enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; | 2542 | enum dc_link_rate link_rate = LINK_RATE_UNKNOWN; |
2541 | uint8_t link_rate_set = 0; | ||
2542 | 2543 | ||
2543 | retrieve_link_cap(link); | 2544 | retrieve_link_cap(link); |
2544 | 2545 | ||
@@ -2558,39 +2559,7 @@ void detect_edp_sink_caps(struct dc_link *link) | |||
2558 | link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz); | 2559 | link_rate = linkRateInKHzToLinkRateMultiplier(link_rate_in_khz); |
2559 | if (link->reported_link_cap.link_rate < link_rate) { | 2560 | if (link->reported_link_cap.link_rate < link_rate) { |
2560 | link->reported_link_cap.link_rate = link_rate; | 2561 | link->reported_link_cap.link_rate = link_rate; |
2561 | 2562 | link->dpcd_caps.link_rate_set = entry; | |
2562 | switch (link_rate) { | ||
2563 | case LINK_RATE_LOW: | ||
2564 | link_rate_set = 1; | ||
2565 | break; | ||
2566 | case LINK_RATE_RATE_2: | ||
2567 | link_rate_set = 2; | ||
2568 | break; | ||
2569 | case LINK_RATE_RATE_3: | ||
2570 | link_rate_set = 3; | ||
2571 | break; | ||
2572 | case LINK_RATE_HIGH: | ||
2573 | link_rate_set = 4; | ||
2574 | break; | ||
2575 | case LINK_RATE_RBR2: | ||
2576 | link_rate_set = 5; | ||
2577 | break; | ||
2578 | case LINK_RATE_RATE_6: | ||
2579 | link_rate_set = 6; | ||
2580 | break; | ||
2581 | case LINK_RATE_HIGH2: | ||
2582 | link_rate_set = 7; | ||
2583 | break; | ||
2584 | case LINK_RATE_HIGH3: | ||
2585 | link_rate_set = 8; | ||
2586 | break; | ||
2587 | default: | ||
2588 | link_rate_set = 0; | ||
2589 | break; | ||
2590 | } | ||
2591 | |||
2592 | if (link->dpcd_caps.link_rate_set < link_rate_set) | ||
2593 | link->dpcd_caps.link_rate_set = link_rate_set; | ||
2594 | } | 2563 | } |
2595 | } | 2564 | } |
2596 | } | 2565 | } |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 16d441d3af8a..f7f7515f65f4 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | |||
@@ -119,6 +119,10 @@ bool edp_receiver_ready_T9(struct dc_link *link) | |||
119 | break; | 119 | break; |
120 | udelay(100); //MAx T9 | 120 | udelay(100); //MAx T9 |
121 | } while (++tries < 50); | 121 | } while (++tries < 50); |
122 | |||
123 | if (link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off > 0) | ||
124 | udelay(link->local_sink->edid_caps.panel_patch.extra_delay_backlight_off * 1000); | ||
125 | |||
122 | return result; | 126 | return result; |
123 | } | 127 | } |
124 | bool edp_receiver_ready_T7(struct dc_link *link) | 128 | bool edp_receiver_ready_T7(struct dc_link *link) |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 9888bc7659f3..349ab8017776 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c | |||
@@ -1800,6 +1800,51 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream) | |||
1800 | stream->phy_pix_clk *= 2; | 1800 | stream->phy_pix_clk *= 2; |
1801 | } | 1801 | } |
1802 | 1802 | ||
1803 | static int acquire_resource_from_hw_enabled_state( | ||
1804 | struct resource_context *res_ctx, | ||
1805 | const struct resource_pool *pool, | ||
1806 | struct dc_stream_state *stream) | ||
1807 | { | ||
1808 | struct dc_link *link = stream->link; | ||
1809 | unsigned int inst; | ||
1810 | |||
1811 | /* Check for enabled DIG to identify enabled display */ | ||
1812 | if (!link->link_enc->funcs->is_dig_enabled(link->link_enc)) | ||
1813 | return -1; | ||
1814 | |||
1815 | /* Check for which front end is used by this encoder. | ||
1816 | * Note the inst is 1 indexed, where 0 is undefined. | ||
1817 | * Note that DIG_FE can source from different OTG but our | ||
1818 | * current implementation always map 1-to-1, so this code makes | ||
1819 | * the same assumption and doesn't check OTG source. | ||
1820 | */ | ||
1821 | inst = link->link_enc->funcs->get_dig_frontend(link->link_enc) - 1; | ||
1822 | |||
1823 | /* Instance should be within the range of the pool */ | ||
1824 | if (inst >= pool->pipe_count) | ||
1825 | return -1; | ||
1826 | |||
1827 | if (!res_ctx->pipe_ctx[inst].stream) { | ||
1828 | struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[inst]; | ||
1829 | |||
1830 | pipe_ctx->stream_res.tg = pool->timing_generators[inst]; | ||
1831 | pipe_ctx->plane_res.mi = pool->mis[inst]; | ||
1832 | pipe_ctx->plane_res.hubp = pool->hubps[inst]; | ||
1833 | pipe_ctx->plane_res.ipp = pool->ipps[inst]; | ||
1834 | pipe_ctx->plane_res.xfm = pool->transforms[inst]; | ||
1835 | pipe_ctx->plane_res.dpp = pool->dpps[inst]; | ||
1836 | pipe_ctx->stream_res.opp = pool->opps[inst]; | ||
1837 | if (pool->dpps[inst]) | ||
1838 | pipe_ctx->plane_res.mpcc_inst = pool->dpps[inst]->inst; | ||
1839 | pipe_ctx->pipe_idx = inst; | ||
1840 | |||
1841 | pipe_ctx->stream = stream; | ||
1842 | return inst; | ||
1843 | } | ||
1844 | |||
1845 | return -1; | ||
1846 | } | ||
1847 | |||
1803 | enum dc_status resource_map_pool_resources( | 1848 | enum dc_status resource_map_pool_resources( |
1804 | const struct dc *dc, | 1849 | const struct dc *dc, |
1805 | struct dc_state *context, | 1850 | struct dc_state *context, |
@@ -1824,8 +1869,15 @@ enum dc_status resource_map_pool_resources( | |||
1824 | 1869 | ||
1825 | calculate_phy_pix_clks(stream); | 1870 | calculate_phy_pix_clks(stream); |
1826 | 1871 | ||
1827 | /* acquire new resources */ | 1872 | if (stream->apply_seamless_boot_optimization) |
1828 | pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); | 1873 | pipe_idx = acquire_resource_from_hw_enabled_state( |
1874 | &context->res_ctx, | ||
1875 | pool, | ||
1876 | stream); | ||
1877 | |||
1878 | if (pipe_idx < 0) | ||
1879 | /* acquire new resources */ | ||
1880 | pipe_idx = acquire_first_free_pipe(&context->res_ctx, pool, stream); | ||
1829 | 1881 | ||
1830 | #ifdef CONFIG_DRM_AMD_DC_DCN1_0 | 1882 | #ifdef CONFIG_DRM_AMD_DC_DCN1_0 |
1831 | if (pipe_idx < 0) | 1883 | if (pipe_idx < 0) |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c index e54b8ac339b2..6ce87b682a32 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c | |||
@@ -112,16 +112,12 @@ uint8_t get_vmid_for_ptb(struct vm_helper *vm_helper, int64_t ptb, uint8_t hubp_ | |||
112 | return vmid; | 112 | return vmid; |
113 | } | 113 | } |
114 | 114 | ||
115 | struct vm_helper init_vm_helper(unsigned int num_vmid, unsigned int num_hubp) | 115 | void init_vm_helper(struct vm_helper *vm_helper, unsigned int num_vmid, unsigned int num_hubp) |
116 | { | 116 | { |
117 | static uint64_t ptb_assigned_to_vmid[MAX_VMID]; | 117 | vm_helper->num_vmid = num_vmid; |
118 | static struct vmid_usage hubp_vmid_usage[MAX_HUBP]; | 118 | vm_helper->num_hubp = num_hubp; |
119 | 119 | vm_helper->num_vmids_available = num_vmid - 1; | |
120 | return (struct vm_helper){ | 120 | |
121 | .num_vmid = num_vmid, | 121 | memset(vm_helper->hubp_vmid_usage, 0, sizeof(vm_helper->hubp_vmid_usage[0]) * MAX_HUBP); |
122 | .num_hubp = num_hubp, | 122 | memset(vm_helper->ptb_assigned_to_vmid, 0, sizeof(vm_helper->ptb_assigned_to_vmid[0]) * MAX_VMID); |
123 | .num_vmids_available = num_vmid - 1, | ||
124 | .ptb_assigned_to_vmid = ptb_assigned_to_vmid, | ||
125 | .hubp_vmid_usage = hubp_vmid_usage | ||
126 | }; | ||
127 | } | 123 | } |
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 8391bc39b7a9..1a7fd6aa77eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h | |||
@@ -39,7 +39,7 @@ | |||
39 | #include "inc/hw/dmcu.h" | 39 | #include "inc/hw/dmcu.h" |
40 | #include "dml/display_mode_lib.h" | 40 | #include "dml/display_mode_lib.h" |
41 | 41 | ||
42 | #define DC_VER "3.2.15" | 42 | #define DC_VER "3.2.17" |
43 | 43 | ||
44 | #define MAX_SURFACES 3 | 44 | #define MAX_SURFACES 3 |
45 | #define MAX_STREAMS 6 | 45 | #define MAX_STREAMS 6 |
@@ -255,6 +255,7 @@ struct dc_debug_options { | |||
255 | bool scl_reset_length10; | 255 | bool scl_reset_length10; |
256 | bool hdmi20_disable; | 256 | bool hdmi20_disable; |
257 | bool skip_detection_link_training; | 257 | bool skip_detection_link_training; |
258 | unsigned int force_odm_combine; //bit vector based on otg inst | ||
258 | unsigned int force_fclk_khz; | 259 | unsigned int force_fclk_khz; |
259 | }; | 260 | }; |
260 | 261 | ||
@@ -264,7 +265,6 @@ struct dc_debug_data { | |||
264 | uint32_t auxErrorCount; | 265 | uint32_t auxErrorCount; |
265 | }; | 266 | }; |
266 | 267 | ||
267 | |||
268 | struct dc_state; | 268 | struct dc_state; |
269 | struct resource_pool; | 269 | struct resource_pool; |
270 | struct dce_hwseq; | 270 | struct dce_hwseq; |
@@ -594,6 +594,10 @@ struct dc_validation_set { | |||
594 | uint8_t plane_count; | 594 | uint8_t plane_count; |
595 | }; | 595 | }; |
596 | 596 | ||
597 | bool dc_validate_seamless_boot_timing(struct dc *dc, | ||
598 | const struct dc_sink *sink, | ||
599 | struct dc_crtc_timing *crtc_timing); | ||
600 | |||
597 | enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); | 601 | enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state); |
598 | 602 | ||
599 | void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info); | 603 | void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info); |
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h index f249ff9be2a7..8fc223defed4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_link.h +++ b/drivers/gpu/drm/amd/display/dc/dc_link.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "grph_object_defs.h" | 30 | #include "grph_object_defs.h" |
31 | 31 | ||
32 | struct dc_link_status { | 32 | struct dc_link_status { |
33 | bool link_active; | ||
33 | struct dpcd_caps *dpcd_caps; | 34 | struct dpcd_caps *dpcd_caps; |
34 | }; | 35 | }; |
35 | 36 | ||
@@ -125,6 +126,7 @@ struct dc_link { | |||
125 | struct dc_link_status link_status; | 126 | struct dc_link_status link_status; |
126 | 127 | ||
127 | struct link_trace link_trace; | 128 | struct link_trace link_trace; |
129 | struct gpio *hpd_gpio; | ||
128 | }; | 130 | }; |
129 | 131 | ||
130 | const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); | 132 | const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link); |
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 0de6d7f377a6..a798694992b9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h | |||
@@ -32,11 +32,17 @@ | |||
32 | /******************************************************************************* | 32 | /******************************************************************************* |
33 | * Stream Interfaces | 33 | * Stream Interfaces |
34 | ******************************************************************************/ | 34 | ******************************************************************************/ |
35 | struct timing_sync_info { | ||
36 | int group_id; | ||
37 | int group_size; | ||
38 | bool master; | ||
39 | }; | ||
35 | 40 | ||
36 | struct dc_stream_status { | 41 | struct dc_stream_status { |
37 | int primary_otg_inst; | 42 | int primary_otg_inst; |
38 | int stream_enc_inst; | 43 | int stream_enc_inst; |
39 | int plane_count; | 44 | int plane_count; |
45 | struct timing_sync_info timing_sync_info; | ||
40 | struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; | 46 | struct dc_plane_state *plane_states[MAX_SURFACE_NUM]; |
41 | }; | 47 | }; |
42 | 48 | ||
@@ -45,11 +51,12 @@ struct freesync_context { | |||
45 | bool dummy; | 51 | bool dummy; |
46 | }; | 52 | }; |
47 | 53 | ||
48 | struct vline_config { | 54 | union vline_config { |
49 | unsigned int start_line; | 55 | unsigned int line_number; |
50 | unsigned int end_line; | 56 | unsigned long long delta_in_ns; |
51 | }; | 57 | }; |
52 | 58 | ||
59 | |||
53 | struct dc_stream_state { | 60 | struct dc_stream_state { |
54 | // sink is deprecated, new code should not reference | 61 | // sink is deprecated, new code should not reference |
55 | // this pointer | 62 | // this pointer |
@@ -99,8 +106,8 @@ struct dc_stream_state { | |||
99 | /* DMCU info */ | 106 | /* DMCU info */ |
100 | unsigned int abm_level; | 107 | unsigned int abm_level; |
101 | 108 | ||
102 | struct vline_config vline0_config; | 109 | union vline_config periodic_vsync_config; |
103 | struct vline_config vline1_config; | 110 | union vline_config enhanced_sync_config; |
104 | 111 | ||
105 | /* from core_stream struct */ | 112 | /* from core_stream struct */ |
106 | struct dc_context *ctx; | 113 | struct dc_context *ctx; |
@@ -112,7 +119,6 @@ struct dc_stream_state { | |||
112 | int phy_pix_clk; | 119 | int phy_pix_clk; |
113 | enum signal_type signal; | 120 | enum signal_type signal; |
114 | bool dpms_off; | 121 | bool dpms_off; |
115 | bool apply_edp_fast_boot_optimization; | ||
116 | 122 | ||
117 | void *dm_stream_context; | 123 | void *dm_stream_context; |
118 | 124 | ||
@@ -139,6 +145,9 @@ struct dc_stream_state { | |||
139 | uint8_t otg_offset; | 145 | uint8_t otg_offset; |
140 | } out; | 146 | } out; |
141 | 147 | ||
148 | bool apply_edp_fast_boot_optimization; | ||
149 | bool apply_seamless_boot_optimization; | ||
150 | |||
142 | uint32_t stream_id; | 151 | uint32_t stream_id; |
143 | }; | 152 | }; |
144 | 153 | ||
@@ -149,8 +158,8 @@ struct dc_stream_update { | |||
149 | struct dc_info_packet *hdr_static_metadata; | 158 | struct dc_info_packet *hdr_static_metadata; |
150 | unsigned int *abm_level; | 159 | unsigned int *abm_level; |
151 | 160 | ||
152 | struct vline_config *vline0_config; | 161 | union vline_config *periodic_vsync_config; |
153 | struct vline_config *vline1_config; | 162 | union vline_config *enhanced_sync_config; |
154 | 163 | ||
155 | struct dc_crtc_timing_adjust *adjust; | 164 | struct dc_crtc_timing_adjust *adjust; |
156 | struct dc_info_packet *vrr_infopacket; | 165 | struct dc_info_packet *vrr_infopacket; |
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 56e7f3dab15a..da2009a108cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h | |||
@@ -201,6 +201,7 @@ union display_content_support { | |||
201 | struct dc_panel_patch { | 201 | struct dc_panel_patch { |
202 | unsigned int dppowerup_delay; | 202 | unsigned int dppowerup_delay; |
203 | unsigned int extra_t12_ms; | 203 | unsigned int extra_t12_ms; |
204 | unsigned int extra_delay_backlight_off; | ||
204 | }; | 205 | }; |
205 | 206 | ||
206 | struct dc_edid_caps { | 207 | struct dc_edid_caps { |
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c index 2a342eae80fd..01e56f1a9f34 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.c | |||
@@ -314,8 +314,8 @@ static bool dce_abm_immediate_disable(struct abm *abm) | |||
314 | 314 | ||
315 | /* setDMCUParam_ABMLevel */ | 315 | /* setDMCUParam_ABMLevel */ |
316 | REG_UPDATE_2(MASTER_COMM_CMD_REG, | 316 | REG_UPDATE_2(MASTER_COMM_CMD_REG, |
317 | MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_LEVEL_SET, | 317 | MASTER_COMM_CMD_REG_BYTE0, MCP_ABM_PIPE_SET, |
318 | MASTER_COMM_CMD_REG_BYTE2, MCP_DISABLE_ABM_IMMEDIATELY); | 318 | MASTER_COMM_CMD_REG_BYTE1, MCP_DISABLE_ABM_IMMEDIATELY); |
319 | 319 | ||
320 | /* notifyDMCUMsg */ | 320 | /* notifyDMCUMsg */ |
321 | REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); | 321 | REG_UPDATE(MASTER_COMM_CNTL_REG, MASTER_COMM_INTERRUPT, 1); |
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c index adbb22224e1a..4febf4ef7240 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c | |||
@@ -516,7 +516,7 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc, | |||
516 | } | 516 | } |
517 | } | 517 | } |
518 | 518 | ||
519 | msleep(1); | 519 | udelay(1000); |
520 | } | 520 | } |
521 | return false; | 521 | return false; |
522 | } | 522 | } |
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index c67e90e5c339..71d5777de961 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c | |||
@@ -977,6 +977,28 @@ static bool dce110_clock_source_power_down( | |||
977 | return bp_result == BP_RESULT_OK; | 977 | return bp_result == BP_RESULT_OK; |
978 | } | 978 | } |
979 | 979 | ||
980 | static bool get_pixel_clk_frequency_100hz( | ||
981 | struct clock_source *clock_source, | ||
982 | unsigned int inst, | ||
983 | unsigned int *pixel_clk_khz) | ||
984 | { | ||
985 | struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source); | ||
986 | unsigned int clock_hz = 0; | ||
987 | |||
988 | if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) { | ||
989 | clock_hz = REG_READ(PHASE[inst]); | ||
990 | |||
991 | /* NOTE: There is agreement with VBIOS here that MODULO is | ||
992 | * programmed equal to DPREFCLK, in which case PHASE will be | ||
993 | * equivalent to pixel clock. | ||
994 | */ | ||
995 | *pixel_clk_khz = clock_hz / 100; | ||
996 | return true; | ||
997 | } | ||
998 | |||
999 | return false; | ||
1000 | } | ||
1001 | |||
980 | /*****************************************/ | 1002 | /*****************************************/ |
981 | /* Constructor */ | 1003 | /* Constructor */ |
982 | /*****************************************/ | 1004 | /*****************************************/ |
@@ -984,12 +1006,14 @@ static bool dce110_clock_source_power_down( | |||
984 | static const struct clock_source_funcs dce112_clk_src_funcs = { | 1006 | static const struct clock_source_funcs dce112_clk_src_funcs = { |
985 | .cs_power_down = dce110_clock_source_power_down, | 1007 | .cs_power_down = dce110_clock_source_power_down, |
986 | .program_pix_clk = dce112_program_pix_clk, | 1008 | .program_pix_clk = dce112_program_pix_clk, |
987 | .get_pix_clk_dividers = dce112_get_pix_clk_dividers | 1009 | .get_pix_clk_dividers = dce112_get_pix_clk_dividers, |
1010 | .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz | ||
988 | }; | 1011 | }; |
989 | static const struct clock_source_funcs dce110_clk_src_funcs = { | 1012 | static const struct clock_source_funcs dce110_clk_src_funcs = { |
990 | .cs_power_down = dce110_clock_source_power_down, | 1013 | .cs_power_down = dce110_clock_source_power_down, |
991 | .program_pix_clk = dce110_program_pix_clk, | 1014 | .program_pix_clk = dce110_program_pix_clk, |
992 | .get_pix_clk_dividers = dce110_get_pix_clk_dividers | 1015 | .get_pix_clk_dividers = dce110_get_pix_clk_dividers, |
1016 | .get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz | ||
993 | }; | 1017 | }; |
994 | 1018 | ||
995 | 1019 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index db0ef41eb91c..e1b285ea01ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | |||
@@ -1032,8 +1032,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, | |||
1032 | struct dc_link *link = stream->link; | 1032 | struct dc_link *link = stream->link; |
1033 | 1033 | ||
1034 | /* only 3 items below are used by unblank */ | 1034 | /* only 3 items below are used by unblank */ |
1035 | params.pixel_clk_khz = | 1035 | params.pixel_clk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10; |
1036 | pipe_ctx->stream->timing.pix_clk_100hz / 10; | ||
1037 | params.link_settings.link_rate = link_settings->link_rate; | 1036 | params.link_settings.link_rate = link_settings->link_rate; |
1038 | 1037 | ||
1039 | if (dc_is_dp_signal(pipe_ctx->stream->signal)) | 1038 | if (dc_is_dp_signal(pipe_ctx->stream->signal)) |
@@ -1043,6 +1042,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, | |||
1043 | link->dc->hwss.edp_backlight_control(link, true); | 1042 | link->dc->hwss.edp_backlight_control(link, true); |
1044 | } | 1043 | } |
1045 | } | 1044 | } |
1045 | |||
1046 | void dce110_blank_stream(struct pipe_ctx *pipe_ctx) | 1046 | void dce110_blank_stream(struct pipe_ctx *pipe_ctx) |
1047 | { | 1047 | { |
1048 | struct dc_stream_state *stream = pipe_ctx->stream; | 1048 | struct dc_stream_state *stream = pipe_ctx->stream; |
@@ -1250,8 +1250,6 @@ static enum dc_status dce110_enable_stream_timing( | |||
1250 | struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. | 1250 | struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. |
1251 | pipe_ctx[pipe_ctx->pipe_idx]; | 1251 | pipe_ctx[pipe_ctx->pipe_idx]; |
1252 | struct tg_color black_color = {0}; | 1252 | struct tg_color black_color = {0}; |
1253 | struct drr_params params = {0}; | ||
1254 | unsigned int event_triggers = 0; | ||
1255 | 1253 | ||
1256 | if (!pipe_ctx_old->stream) { | 1254 | if (!pipe_ctx_old->stream) { |
1257 | 1255 | ||
@@ -1280,20 +1278,6 @@ static enum dc_status dce110_enable_stream_timing( | |||
1280 | pipe_ctx->stream_res.tg, | 1278 | pipe_ctx->stream_res.tg, |
1281 | &stream->timing, | 1279 | &stream->timing, |
1282 | true); | 1280 | true); |
1283 | |||
1284 | params.vertical_total_min = stream->adjust.v_total_min; | ||
1285 | params.vertical_total_max = stream->adjust.v_total_max; | ||
1286 | if (pipe_ctx->stream_res.tg->funcs->set_drr) | ||
1287 | pipe_ctx->stream_res.tg->funcs->set_drr( | ||
1288 | pipe_ctx->stream_res.tg, ¶ms); | ||
1289 | |||
1290 | // DRR should set trigger event to monitor surface update event | ||
1291 | if (stream->adjust.v_total_min != 0 && | ||
1292 | stream->adjust.v_total_max != 0) | ||
1293 | event_triggers = 0x80; | ||
1294 | if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) | ||
1295 | pipe_ctx->stream_res.tg->funcs->set_static_screen_control( | ||
1296 | pipe_ctx->stream_res.tg, event_triggers); | ||
1297 | } | 1281 | } |
1298 | 1282 | ||
1299 | if (!pipe_ctx_old->stream) { | 1283 | if (!pipe_ctx_old->stream) { |
@@ -1313,6 +1297,8 @@ static enum dc_status apply_single_controller_ctx_to_hw( | |||
1313 | struct dc *dc) | 1297 | struct dc *dc) |
1314 | { | 1298 | { |
1315 | struct dc_stream_state *stream = pipe_ctx->stream; | 1299 | struct dc_stream_state *stream = pipe_ctx->stream; |
1300 | struct drr_params params = {0}; | ||
1301 | unsigned int event_triggers = 0; | ||
1316 | 1302 | ||
1317 | if (pipe_ctx->stream_res.audio != NULL) { | 1303 | if (pipe_ctx->stream_res.audio != NULL) { |
1318 | struct audio_output audio_output; | 1304 | struct audio_output audio_output; |
@@ -1339,7 +1325,27 @@ static enum dc_status apply_single_controller_ctx_to_hw( | |||
1339 | } | 1325 | } |
1340 | 1326 | ||
1341 | /* */ | 1327 | /* */ |
1342 | dc->hwss.enable_stream_timing(pipe_ctx, context, dc); | 1328 | /* Do not touch stream timing on seamless boot optimization. */ |
1329 | if (!pipe_ctx->stream->apply_seamless_boot_optimization) | ||
1330 | dc->hwss.enable_stream_timing(pipe_ctx, context, dc); | ||
1331 | |||
1332 | if (pipe_ctx->stream_res.tg->funcs->program_vupdate_interrupt) | ||
1333 | pipe_ctx->stream_res.tg->funcs->program_vupdate_interrupt( | ||
1334 | pipe_ctx->stream_res.tg, | ||
1335 | &stream->timing); | ||
1336 | |||
1337 | params.vertical_total_min = stream->adjust.v_total_min; | ||
1338 | params.vertical_total_max = stream->adjust.v_total_max; | ||
1339 | if (pipe_ctx->stream_res.tg->funcs->set_drr) | ||
1340 | pipe_ctx->stream_res.tg->funcs->set_drr( | ||
1341 | pipe_ctx->stream_res.tg, ¶ms); | ||
1342 | |||
1343 | // DRR should set trigger event to monitor surface update event | ||
1344 | if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) | ||
1345 | event_triggers = 0x80; | ||
1346 | if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) | ||
1347 | pipe_ctx->stream_res.tg->funcs->set_static_screen_control( | ||
1348 | pipe_ctx->stream_res.tg, event_triggers); | ||
1343 | 1349 | ||
1344 | if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) | 1350 | if (pipe_ctx->stream->signal != SIGNAL_TYPE_VIRTUAL) |
1345 | pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( | 1351 | pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg( |
@@ -2269,6 +2275,11 @@ static void dce110_enable_per_frame_crtc_position_reset( | |||
2269 | 2275 | ||
2270 | } | 2276 | } |
2271 | 2277 | ||
2278 | static void init_pipes(struct dc *dc, struct dc_state *context) | ||
2279 | { | ||
2280 | // Do nothing | ||
2281 | } | ||
2282 | |||
2272 | static void init_hw(struct dc *dc) | 2283 | static void init_hw(struct dc *dc) |
2273 | { | 2284 | { |
2274 | int i; | 2285 | int i; |
@@ -2535,7 +2546,7 @@ static void dce110_apply_ctx_for_surface( | |||
2535 | } | 2546 | } |
2536 | 2547 | ||
2537 | if (dc->fbc_compressor) | 2548 | if (dc->fbc_compressor) |
2538 | enable_fbc(dc, dc->current_state); | 2549 | enable_fbc(dc, context); |
2539 | } | 2550 | } |
2540 | 2551 | ||
2541 | static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) | 2552 | static void dce110_power_down_fe(struct dc *dc, struct pipe_ctx *pipe_ctx) |
@@ -2636,6 +2647,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { | |||
2636 | .program_gamut_remap = program_gamut_remap, | 2647 | .program_gamut_remap = program_gamut_remap, |
2637 | .program_output_csc = program_output_csc, | 2648 | .program_output_csc = program_output_csc, |
2638 | .init_hw = init_hw, | 2649 | .init_hw = init_hw, |
2650 | .init_pipes = init_pipes, | ||
2639 | .apply_ctx_to_hw = dce110_apply_ctx_to_hw, | 2651 | .apply_ctx_to_hw = dce110_apply_ctx_to_hw, |
2640 | .apply_ctx_for_surface = dce110_apply_ctx_for_surface, | 2652 | .apply_ctx_for_surface = dce110_apply_ctx_for_surface, |
2641 | .update_plane_addr = update_plane_addr, | 2653 | .update_plane_addr = update_plane_addr, |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c index 5a4614c371bc..e161ad836812 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c | |||
@@ -88,11 +88,18 @@ void hubbub1_wm_read_state(struct hubbub *hubbub, | |||
88 | s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); | 88 | s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D); |
89 | } | 89 | } |
90 | 90 | ||
91 | void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub) | 91 | void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow) |
92 | { | 92 | { |
93 | struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); | 93 | struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); |
94 | REG_UPDATE(DCHUBBUB_ARB_DRAM_STATE_CNTL, | 94 | |
95 | DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, 0); | 95 | /* |
96 | * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 1 means do not allow stutter | ||
97 | * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 means allow stutter | ||
98 | */ | ||
99 | |||
100 | REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, | ||
101 | DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, | ||
102 | DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, !allow); | ||
96 | } | 103 | } |
97 | 104 | ||
98 | bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub) | 105 | bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub) |
@@ -262,8 +269,6 @@ void hubbub1_program_watermarks( | |||
262 | bool safe_to_lower) | 269 | bool safe_to_lower) |
263 | { | 270 | { |
264 | struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); | 271 | struct dcn10_hubbub *hubbub1 = TO_DCN10_HUBBUB(hubbub); |
265 | |||
266 | uint32_t force_en = hubbub1->base.ctx->dc->debug.disable_stutter ? 1 : 0; | ||
267 | /* | 272 | /* |
268 | * Need to clamp to max of the register values (i.e. no wrap) | 273 | * Need to clamp to max of the register values (i.e. no wrap) |
269 | * for dcn1, all wm registers are 21-bit wide | 274 | * for dcn1, all wm registers are 21-bit wide |
@@ -537,9 +542,7 @@ void hubbub1_program_watermarks( | |||
537 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, | 542 | REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND, |
538 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); | 543 | DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 68); |
539 | 544 | ||
540 | REG_UPDATE_2(DCHUBBUB_ARB_DRAM_STATE_CNTL, | 545 | hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); |
541 | DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_VALUE, 0, | ||
542 | DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, force_en); | ||
543 | 546 | ||
544 | #if 0 | 547 | #if 0 |
545 | REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, | 548 | REG_UPDATE_2(DCHUBBUB_ARB_WATERMARK_CHANGE_CNTL, |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h index c681e1cc9290..9cd4a5194154 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h | |||
@@ -204,7 +204,7 @@ void hubbub1_program_watermarks( | |||
204 | unsigned int refclk_mhz, | 204 | unsigned int refclk_mhz, |
205 | bool safe_to_lower); | 205 | bool safe_to_lower); |
206 | 206 | ||
207 | void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub); | 207 | void hubbub1_allow_self_refresh_control(struct hubbub *hubbub, bool allow); |
208 | 208 | ||
209 | bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub); | 209 | bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub); |
210 | 210 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c index 0ba68d41b9c3..683829466a44 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | |||
@@ -1150,9 +1150,28 @@ void hubp1_cursor_set_position( | |||
1150 | REG_UPDATE(CURSOR_CONTROL, | 1150 | REG_UPDATE(CURSOR_CONTROL, |
1151 | CURSOR_ENABLE, cur_en); | 1151 | CURSOR_ENABLE, cur_en); |
1152 | 1152 | ||
1153 | REG_SET_2(CURSOR_POSITION, 0, | 1153 | //account for cases where we see negative offset relative to overlay plane |
1154 | CURSOR_X_POSITION, pos->x, | 1154 | if (src_x_offset < 0 && src_y_offset < 0) { |
1155 | REG_SET_2(CURSOR_POSITION, 0, | ||
1156 | CURSOR_X_POSITION, 0, | ||
1157 | CURSOR_Y_POSITION, 0); | ||
1158 | x_hotspot -= src_x_offset; | ||
1159 | y_hotspot -= src_y_offset; | ||
1160 | } else if (src_x_offset < 0) { | ||
1161 | REG_SET_2(CURSOR_POSITION, 0, | ||
1162 | CURSOR_X_POSITION, 0, | ||
1155 | CURSOR_Y_POSITION, pos->y); | 1163 | CURSOR_Y_POSITION, pos->y); |
1164 | x_hotspot -= src_x_offset; | ||
1165 | } else if (src_y_offset < 0) { | ||
1166 | REG_SET_2(CURSOR_POSITION, 0, | ||
1167 | CURSOR_X_POSITION, pos->x, | ||
1168 | CURSOR_Y_POSITION, 0); | ||
1169 | y_hotspot -= src_y_offset; | ||
1170 | } else { | ||
1171 | REG_SET_2(CURSOR_POSITION, 0, | ||
1172 | CURSOR_X_POSITION, pos->x, | ||
1173 | CURSOR_Y_POSITION, pos->y); | ||
1174 | } | ||
1156 | 1175 | ||
1157 | REG_SET_2(CURSOR_HOT_SPOT, 0, | 1176 | REG_SET_2(CURSOR_HOT_SPOT, 0, |
1158 | CURSOR_HOT_SPOT_X, x_hotspot, | 1177 | CURSOR_HOT_SPOT_X, x_hotspot, |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 9cde24dbdac8..117d9d8227f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | |||
@@ -636,8 +636,6 @@ static enum dc_status dcn10_enable_stream_timing( | |||
636 | struct dc_stream_state *stream = pipe_ctx->stream; | 636 | struct dc_stream_state *stream = pipe_ctx->stream; |
637 | enum dc_color_space color_space; | 637 | enum dc_color_space color_space; |
638 | struct tg_color black_color = {0}; | 638 | struct tg_color black_color = {0}; |
639 | struct drr_params params = {0}; | ||
640 | unsigned int event_triggers = 0; | ||
641 | 639 | ||
642 | /* by upper caller loop, pipe0 is parent pipe and be called first. | 640 | /* by upper caller loop, pipe0 is parent pipe and be called first. |
643 | * back end is set up by for pipe0. Other children pipe share back end | 641 | * back end is set up by for pipe0. Other children pipe share back end |
@@ -705,19 +703,6 @@ static enum dc_status dcn10_enable_stream_timing( | |||
705 | return DC_ERROR_UNEXPECTED; | 703 | return DC_ERROR_UNEXPECTED; |
706 | } | 704 | } |
707 | 705 | ||
708 | params.vertical_total_min = stream->adjust.v_total_min; | ||
709 | params.vertical_total_max = stream->adjust.v_total_max; | ||
710 | if (pipe_ctx->stream_res.tg->funcs->set_drr) | ||
711 | pipe_ctx->stream_res.tg->funcs->set_drr( | ||
712 | pipe_ctx->stream_res.tg, ¶ms); | ||
713 | |||
714 | // DRR should set trigger event to monitor surface update event | ||
715 | if (stream->adjust.v_total_min != 0 && stream->adjust.v_total_max != 0) | ||
716 | event_triggers = 0x80; | ||
717 | if (pipe_ctx->stream_res.tg->funcs->set_static_screen_control) | ||
718 | pipe_ctx->stream_res.tg->funcs->set_static_screen_control( | ||
719 | pipe_ctx->stream_res.tg, event_triggers); | ||
720 | |||
721 | /* TODO program crtc source select for non-virtual signal*/ | 706 | /* TODO program crtc source select for non-virtual signal*/ |
722 | /* TODO program FMT */ | 707 | /* TODO program FMT */ |
723 | /* TODO setup link_enc */ | 708 | /* TODO setup link_enc */ |
@@ -971,92 +956,34 @@ static void dcn10_disable_plane(struct dc *dc, struct pipe_ctx *pipe_ctx) | |||
971 | pipe_ctx->pipe_idx); | 956 | pipe_ctx->pipe_idx); |
972 | } | 957 | } |
973 | 958 | ||
974 | static void dcn10_init_hw(struct dc *dc) | 959 | static void dcn10_init_pipes(struct dc *dc, struct dc_state *context) |
975 | { | 960 | { |
976 | int i; | 961 | int i; |
977 | struct abm *abm = dc->res_pool->abm; | ||
978 | struct dmcu *dmcu = dc->res_pool->dmcu; | ||
979 | struct dce_hwseq *hws = dc->hwseq; | ||
980 | struct dc_bios *dcb = dc->ctx->dc_bios; | ||
981 | struct dc_state *context = dc->current_state; | ||
982 | |||
983 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { | ||
984 | REG_WRITE(REFCLK_CNTL, 0); | ||
985 | REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); | ||
986 | REG_WRITE(DIO_MEM_PWR_CTRL, 0); | ||
987 | |||
988 | if (!dc->debug.disable_clock_gate) { | ||
989 | /* enable all DCN clock gating */ | ||
990 | REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); | ||
991 | |||
992 | REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); | ||
993 | |||
994 | REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); | ||
995 | } | ||
996 | |||
997 | enable_power_gating_plane(dc->hwseq, true); | ||
998 | } else { | ||
999 | |||
1000 | if (!dcb->funcs->is_accelerated_mode(dcb)) { | ||
1001 | bool allow_self_fresh_force_enable = | ||
1002 | hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub); | ||
1003 | |||
1004 | bios_golden_init(dc); | ||
1005 | |||
1006 | /* WA for making DF sleep when idle after resume from S0i3. | ||
1007 | * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by | ||
1008 | * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 | ||
1009 | * before calling command table and it changed to 1 after, | ||
1010 | * it should be set back to 0. | ||
1011 | */ | ||
1012 | if (allow_self_fresh_force_enable == false && | ||
1013 | hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub)) | ||
1014 | hubbub1_disable_allow_self_refresh(dc->res_pool->hubbub); | ||
1015 | |||
1016 | disable_vga(dc->hwseq); | ||
1017 | } | ||
1018 | |||
1019 | for (i = 0; i < dc->link_count; i++) { | ||
1020 | /* Power up AND update implementation according to the | ||
1021 | * required signal (which may be different from the | ||
1022 | * default signal on connector). | ||
1023 | */ | ||
1024 | struct dc_link *link = dc->links[i]; | ||
1025 | |||
1026 | if (link->link_enc->connector.id == CONNECTOR_ID_EDP) | ||
1027 | dc->hwss.edp_power_control(link, true); | ||
1028 | |||
1029 | link->link_enc->funcs->hw_init(link->link_enc); | ||
1030 | } | ||
1031 | } | ||
1032 | 962 | ||
1033 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | 963 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
1034 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | 964 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; |
1035 | 965 | ||
1036 | if (tg->funcs->is_tg_enabled(tg)) | 966 | if (tg->funcs->is_tg_enabled(tg)) |
1037 | tg->funcs->lock(tg); | 967 | tg->funcs->lock(tg); |
1038 | } | ||
1039 | |||
1040 | /* Blank controller using driver code instead of | ||
1041 | * command table. | ||
1042 | */ | ||
1043 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
1044 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | ||
1045 | 968 | ||
969 | /* Blank controller using driver code instead of | ||
970 | * command table. | ||
971 | */ | ||
1046 | if (tg->funcs->is_tg_enabled(tg)) { | 972 | if (tg->funcs->is_tg_enabled(tg)) { |
1047 | tg->funcs->set_blank(tg, true); | 973 | tg->funcs->set_blank(tg, true); |
1048 | hwss_wait_for_blank_complete(tg); | 974 | hwss_wait_for_blank_complete(tg); |
1049 | } | 975 | } |
1050 | } | 976 | } |
1051 | 977 | ||
1052 | /* Reset all MPCC muxes */ | ||
1053 | dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc); | 978 | dc->res_pool->mpc->funcs->mpc_init(dc->res_pool->mpc); |
1054 | 979 | ||
1055 | for (i = 0; i < dc->res_pool->timing_generator_count; i++) { | 980 | for (i = 0; i < dc->res_pool->pipe_count; i++) { |
1056 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | 981 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; |
1057 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | ||
1058 | struct hubp *hubp = dc->res_pool->hubps[i]; | 982 | struct hubp *hubp = dc->res_pool->hubps[i]; |
1059 | struct dpp *dpp = dc->res_pool->dpps[i]; | 983 | struct dpp *dpp = dc->res_pool->dpps[i]; |
984 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | ||
985 | |||
986 | dpp->funcs->dpp_reset(dpp); | ||
1060 | 987 | ||
1061 | pipe_ctx->stream_res.tg = tg; | 988 | pipe_ctx->stream_res.tg = tg; |
1062 | pipe_ctx->pipe_idx = i; | 989 | pipe_ctx->pipe_idx = i; |
@@ -1074,18 +1001,9 @@ static void dcn10_init_hw(struct dc *dc) | |||
1074 | pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; | 1001 | pipe_ctx->stream_res.opp = dc->res_pool->opps[i]; |
1075 | 1002 | ||
1076 | hwss1_plane_atomic_disconnect(dc, pipe_ctx); | 1003 | hwss1_plane_atomic_disconnect(dc, pipe_ctx); |
1077 | } | ||
1078 | |||
1079 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
1080 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | ||
1081 | 1004 | ||
1082 | if (tg->funcs->is_tg_enabled(tg)) | 1005 | if (tg->funcs->is_tg_enabled(tg)) |
1083 | tg->funcs->unlock(tg); | 1006 | tg->funcs->unlock(tg); |
1084 | } | ||
1085 | |||
1086 | for (i = 0; i < dc->res_pool->pipe_count; i++) { | ||
1087 | struct timing_generator *tg = dc->res_pool->timing_generators[i]; | ||
1088 | struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; | ||
1089 | 1007 | ||
1090 | dcn10_disable_plane(dc, pipe_ctx); | 1008 | dcn10_disable_plane(dc, pipe_ctx); |
1091 | 1009 | ||
@@ -1094,10 +1012,73 @@ static void dcn10_init_hw(struct dc *dc) | |||
1094 | 1012 | ||
1095 | tg->funcs->tg_init(tg); | 1013 | tg->funcs->tg_init(tg); |
1096 | } | 1014 | } |
1015 | } | ||
1016 | |||
1017 | static void dcn10_init_hw(struct dc *dc) | ||
1018 | { | ||
1019 | int i; | ||
1020 | struct abm *abm = dc->res_pool->abm; | ||
1021 | struct dmcu *dmcu = dc->res_pool->dmcu; | ||
1022 | struct dce_hwseq *hws = dc->hwseq; | ||
1023 | struct dc_bios *dcb = dc->ctx->dc_bios; | ||
1024 | |||
1025 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { | ||
1026 | REG_WRITE(REFCLK_CNTL, 0); | ||
1027 | REG_UPDATE(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, 1); | ||
1028 | REG_WRITE(DIO_MEM_PWR_CTRL, 0); | ||
1029 | |||
1030 | if (!dc->debug.disable_clock_gate) { | ||
1031 | /* enable all DCN clock gating */ | ||
1032 | REG_WRITE(DCCG_GATE_DISABLE_CNTL, 0); | ||
1033 | |||
1034 | REG_WRITE(DCCG_GATE_DISABLE_CNTL2, 0); | ||
1035 | |||
1036 | REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0); | ||
1037 | } | ||
1038 | |||
1039 | enable_power_gating_plane(dc->hwseq, true); | ||
1097 | 1040 | ||
1098 | /* end of FPGA. Below if real ASIC */ | 1041 | /* end of FPGA. Below if real ASIC */ |
1099 | if (IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) | ||
1100 | return; | 1042 | return; |
1043 | } | ||
1044 | |||
1045 | if (!dcb->funcs->is_accelerated_mode(dcb)) { | ||
1046 | bool allow_self_fresh_force_enable = | ||
1047 | hububu1_is_allow_self_refresh_enabled( | ||
1048 | dc->res_pool->hubbub); | ||
1049 | |||
1050 | bios_golden_init(dc); | ||
1051 | |||
1052 | /* WA for making DF sleep when idle after resume from S0i3. | ||
1053 | * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by | ||
1054 | * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0 | ||
1055 | * before calling command table and it changed to 1 after, | ||
1056 | * it should be set back to 0. | ||
1057 | */ | ||
1058 | if (allow_self_fresh_force_enable == false && | ||
1059 | hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub)) | ||
1060 | hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, true); | ||
1061 | |||
1062 | disable_vga(dc->hwseq); | ||
1063 | } | ||
1064 | |||
1065 | for (i = 0; i < dc->link_count; i++) { | ||
1066 | /* Power up AND update implementation according to the | ||
1067 | * required signal (which may be different from the | ||
1068 | * default signal on connector). | ||
1069 | */ | ||
1070 | struct dc_link *link = dc->links[i]; | ||
1071 | |||
1072 | if (link->link_enc->connector.id == CONNECTOR_ID_EDP) | ||
1073 | dc->hwss.edp_power_control(link, true); | ||
1074 | |||
1075 | link->link_enc->funcs->hw_init(link->link_enc); | ||
1076 | |||
1077 | /* Check for enabled DIG to identify enabled display */ | ||
1078 | if (link->link_enc->funcs->is_dig_enabled && | ||
1079 | link->link_enc->funcs->is_dig_enabled(link->link_enc)) | ||
1080 | link->link_status.link_active = true; | ||
1081 | } | ||
1101 | 1082 | ||
1102 | for (i = 0; i < dc->res_pool->audio_count; i++) { | 1083 | for (i = 0; i < dc->res_pool->audio_count; i++) { |
1103 | struct audio *audio = dc->res_pool->audios[i]; | 1084 | struct audio *audio = dc->res_pool->audios[i]; |
@@ -1128,6 +1109,9 @@ static void dcn10_init_hw(struct dc *dc) | |||
1128 | enable_power_gating_plane(dc->hwseq, true); | 1109 | enable_power_gating_plane(dc->hwseq, true); |
1129 | 1110 | ||
1130 | memset(&dc->res_pool->clk_mgr->clks, 0, sizeof(dc->res_pool->clk_mgr->clks)); | 1111 | memset(&dc->res_pool->clk_mgr->clks, 0, sizeof(dc->res_pool->clk_mgr->clks)); |
1112 | |||
1113 | if (dc->hwss.init_pipes) | ||
1114 | dc->hwss.init_pipes(dc, dc->current_state); | ||
1131 | } | 1115 | } |
1132 | 1116 | ||
1133 | static void reset_hw_ctx_wrap( | 1117 | static void reset_hw_ctx_wrap( |
@@ -2334,9 +2318,10 @@ static void dcn10_apply_ctx_for_surface( | |||
2334 | } | 2318 | } |
2335 | } | 2319 | } |
2336 | 2320 | ||
2337 | if (!pipe_ctx->plane_state && | 2321 | if ((!pipe_ctx->plane_state || |
2338 | old_pipe_ctx->plane_state && | 2322 | pipe_ctx->stream_res.tg != old_pipe_ctx->stream_res.tg) && |
2339 | old_pipe_ctx->stream_res.tg == tg) { | 2323 | old_pipe_ctx->plane_state && |
2324 | old_pipe_ctx->stream_res.tg == tg) { | ||
2340 | 2325 | ||
2341 | dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx); | 2326 | dc->hwss.plane_atomic_disconnect(dc, old_pipe_ctx); |
2342 | removed_pipe[i] = true; | 2327 | removed_pipe[i] = true; |
@@ -2383,6 +2368,22 @@ static void dcn10_apply_ctx_for_surface( | |||
2383 | hubbub1_wm_change_req_wa(dc->res_pool->hubbub); | 2368 | hubbub1_wm_change_req_wa(dc->res_pool->hubbub); |
2384 | } | 2369 | } |
2385 | 2370 | ||
2371 | static void dcn10_stereo_hw_frame_pack_wa(struct dc *dc, struct dc_state *context) | ||
2372 | { | ||
2373 | uint8_t i; | ||
2374 | |||
2375 | for (i = 0; i < context->stream_count; i++) { | ||
2376 | if (context->streams[i]->timing.timing_3d_format | ||
2377 | == TIMING_3D_FORMAT_HW_FRAME_PACKING) { | ||
2378 | /* | ||
2379 | * Disable stutter | ||
2380 | */ | ||
2381 | hubbub1_allow_self_refresh_control(dc->res_pool->hubbub, false); | ||
2382 | break; | ||
2383 | } | ||
2384 | } | ||
2385 | } | ||
2386 | |||
2386 | static void dcn10_prepare_bandwidth( | 2387 | static void dcn10_prepare_bandwidth( |
2387 | struct dc *dc, | 2388 | struct dc *dc, |
2388 | struct dc_state *context) | 2389 | struct dc_state *context) |
@@ -2404,6 +2405,7 @@ static void dcn10_prepare_bandwidth( | |||
2404 | &context->bw.dcn.watermarks, | 2405 | &context->bw.dcn.watermarks, |
2405 | dc->res_pool->ref_clock_inKhz / 1000, | 2406 | dc->res_pool->ref_clock_inKhz / 1000, |
2406 | true); | 2407 | true); |
2408 | dcn10_stereo_hw_frame_pack_wa(dc, context); | ||
2407 | 2409 | ||
2408 | if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) | 2410 | if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) |
2409 | dcn_bw_notify_pplib_of_wm_ranges(dc); | 2411 | dcn_bw_notify_pplib_of_wm_ranges(dc); |
@@ -2433,6 +2435,7 @@ static void dcn10_optimize_bandwidth( | |||
2433 | &context->bw.dcn.watermarks, | 2435 | &context->bw.dcn.watermarks, |
2434 | dc->res_pool->ref_clock_inKhz / 1000, | 2436 | dc->res_pool->ref_clock_inKhz / 1000, |
2435 | true); | 2437 | true); |
2438 | dcn10_stereo_hw_frame_pack_wa(dc, context); | ||
2436 | 2439 | ||
2437 | if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) | 2440 | if (dc->debug.pplib_wm_report_mode == WM_REPORT_OVERRIDE) |
2438 | dcn_bw_notify_pplib_of_wm_ranges(dc); | 2441 | dcn_bw_notify_pplib_of_wm_ranges(dc); |
@@ -2709,6 +2712,7 @@ static void dcn10_set_cursor_sdr_white_level(struct pipe_ctx *pipe_ctx) | |||
2709 | static const struct hw_sequencer_funcs dcn10_funcs = { | 2712 | static const struct hw_sequencer_funcs dcn10_funcs = { |
2710 | .program_gamut_remap = program_gamut_remap, | 2713 | .program_gamut_remap = program_gamut_remap, |
2711 | .init_hw = dcn10_init_hw, | 2714 | .init_hw = dcn10_init_hw, |
2715 | .init_pipes = dcn10_init_pipes, | ||
2712 | .apply_ctx_to_hw = dce110_apply_ctx_to_hw, | 2716 | .apply_ctx_to_hw = dce110_apply_ctx_to_hw, |
2713 | .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, | 2717 | .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, |
2714 | .update_plane_addr = dcn10_update_plane_addr, | 2718 | .update_plane_addr = dcn10_update_plane_addr, |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c index 771449f8984f..a9db372688ff 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c | |||
@@ -85,6 +85,7 @@ static const struct link_encoder_funcs dcn10_lnk_enc_funcs = { | |||
85 | .enable_hpd = dcn10_link_encoder_enable_hpd, | 85 | .enable_hpd = dcn10_link_encoder_enable_hpd, |
86 | .disable_hpd = dcn10_link_encoder_disable_hpd, | 86 | .disable_hpd = dcn10_link_encoder_disable_hpd, |
87 | .is_dig_enabled = dcn10_is_dig_enabled, | 87 | .is_dig_enabled = dcn10_is_dig_enabled, |
88 | .get_dig_frontend = dcn10_get_dig_frontend, | ||
88 | .destroy = dcn10_link_encoder_destroy | 89 | .destroy = dcn10_link_encoder_destroy |
89 | }; | 90 | }; |
90 | 91 | ||
@@ -495,6 +496,15 @@ bool dcn10_is_dig_enabled(struct link_encoder *enc) | |||
495 | return value; | 496 | return value; |
496 | } | 497 | } |
497 | 498 | ||
499 | unsigned int dcn10_get_dig_frontend(struct link_encoder *enc) | ||
500 | { | ||
501 | struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); | ||
502 | uint32_t value; | ||
503 | |||
504 | REG_GET(DIG_BE_CNTL, DIG_FE_SOURCE_SELECT, &value); | ||
505 | return value; | ||
506 | } | ||
507 | |||
498 | static void link_encoder_disable(struct dcn10_link_encoder *enc10) | 508 | static void link_encoder_disable(struct dcn10_link_encoder *enc10) |
499 | { | 509 | { |
500 | /* reset training pattern */ | 510 | /* reset training pattern */ |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index 670b46e887ed..b74b80a247ec 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h | |||
@@ -336,6 +336,8 @@ void dcn10_psr_program_secondary_packet(struct link_encoder *enc, | |||
336 | 336 | ||
337 | bool dcn10_is_dig_enabled(struct link_encoder *enc); | 337 | bool dcn10_is_dig_enabled(struct link_encoder *enc); |
338 | 338 | ||
339 | unsigned int dcn10_get_dig_frontend(struct link_encoder *enc); | ||
340 | |||
339 | void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); | 341 | void dcn10_aux_initialize(struct dcn10_link_encoder *enc10); |
340 | 342 | ||
341 | #endif /* __DC_LINK_ENCODER__DCN10_H__ */ | 343 | #endif /* __DC_LINK_ENCODER__DCN10_H__ */ |
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index 1d4f9b48ed7d..2f78a84f0dcb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | |||
@@ -92,28 +92,136 @@ static void optc1_disable_stereo(struct timing_generator *optc) | |||
92 | OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); | 92 | OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0); |
93 | } | 93 | } |
94 | 94 | ||
95 | static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing) | ||
96 | { | ||
97 | struct dc_crtc_timing patched_crtc_timing; | ||
98 | int vesa_sync_start; | ||
99 | int asic_blank_end; | ||
100 | int interlace_factor; | ||
101 | int vertical_line_start; | ||
102 | |||
103 | patched_crtc_timing = *dc_crtc_timing; | ||
104 | optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); | ||
105 | |||
106 | vesa_sync_start = patched_crtc_timing.h_addressable + | ||
107 | patched_crtc_timing.h_border_right + | ||
108 | patched_crtc_timing.h_front_porch; | ||
109 | |||
110 | asic_blank_end = patched_crtc_timing.h_total - | ||
111 | vesa_sync_start - | ||
112 | patched_crtc_timing.h_border_left; | ||
113 | |||
114 | interlace_factor = patched_crtc_timing.flags.INTERLACE ? 2 : 1; | ||
115 | |||
116 | vesa_sync_start = patched_crtc_timing.v_addressable + | ||
117 | patched_crtc_timing.v_border_bottom + | ||
118 | patched_crtc_timing.v_front_porch; | ||
119 | |||
120 | asic_blank_end = (patched_crtc_timing.v_total - | ||
121 | vesa_sync_start - | ||
122 | patched_crtc_timing.v_border_top) | ||
123 | * interlace_factor; | ||
124 | |||
125 | vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; | ||
126 | if (vertical_line_start < 0) { | ||
127 | ASSERT(0); | ||
128 | vertical_line_start = 0; | ||
129 | } | ||
130 | |||
131 | return vertical_line_start; | ||
132 | } | ||
133 | |||
134 | static void calc_vline_position( | ||
135 | struct timing_generator *optc, | ||
136 | const struct dc_crtc_timing *dc_crtc_timing, | ||
137 | unsigned long long vsync_delta, | ||
138 | uint32_t *start_line, | ||
139 | uint32_t *end_line) | ||
140 | { | ||
141 | unsigned long long req_delta_tens_of_usec = div64_u64((vsync_delta + 9999), 10000); | ||
142 | unsigned long long pix_clk_hundreds_khz = div64_u64((dc_crtc_timing->pix_clk_100hz + 999), 1000); | ||
143 | uint32_t req_delta_lines = (uint32_t) div64_u64( | ||
144 | (req_delta_tens_of_usec * pix_clk_hundreds_khz + dc_crtc_timing->h_total - 1), | ||
145 | dc_crtc_timing->h_total); | ||
146 | |||
147 | uint32_t vsync_line = get_start_vline(optc, dc_crtc_timing); | ||
148 | |||
149 | if (req_delta_lines != 0) | ||
150 | req_delta_lines--; | ||
151 | |||
152 | if (req_delta_lines > vsync_line) | ||
153 | *start_line = dc_crtc_timing->v_total - (req_delta_lines - vsync_line) - 1; | ||
154 | else | ||
155 | *start_line = vsync_line - req_delta_lines; | ||
156 | |||
157 | *end_line = *start_line + 2; | ||
158 | |||
159 | if (*end_line >= dc_crtc_timing->v_total) | ||
160 | *end_line = 2; | ||
161 | } | ||
162 | |||
95 | void optc1_program_vline_interrupt( | 163 | void optc1_program_vline_interrupt( |
96 | struct timing_generator *optc, | 164 | struct timing_generator *optc, |
165 | const struct dc_crtc_timing *dc_crtc_timing, | ||
97 | enum vline_select vline, | 166 | enum vline_select vline, |
98 | struct vline_config vline_config) | 167 | const union vline_config *vline_config) |
99 | { | 168 | { |
100 | struct optc *optc1 = DCN10TG_FROM_TG(optc); | 169 | struct optc *optc1 = DCN10TG_FROM_TG(optc); |
170 | uint32_t start_line = 0; | ||
171 | uint32_t end_line = 0; | ||
101 | 172 | ||
102 | switch (vline) { | 173 | switch (vline) { |
103 | case VLINE0: | 174 | case VLINE0: |
175 | calc_vline_position(optc, dc_crtc_timing, vline_config->delta_in_ns, &start_line, &end_line); | ||
104 | REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0, | 176 | REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0, |
105 | OTG_VERTICAL_INTERRUPT0_LINE_START, vline_config.start_line, | 177 | OTG_VERTICAL_INTERRUPT0_LINE_START, start_line, |
106 | OTG_VERTICAL_INTERRUPT0_LINE_END, vline_config.end_line); | 178 | OTG_VERTICAL_INTERRUPT0_LINE_END, end_line); |
107 | break; | 179 | break; |
108 | case VLINE1: | 180 | case VLINE1: |
109 | REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0, | 181 | REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0, |
110 | OTG_VERTICAL_INTERRUPT1_LINE_START, vline_config.start_line); | 182 | OTG_VERTICAL_INTERRUPT1_LINE_START, vline_config->line_number); |
111 | break; | 183 | break; |
112 | default: | 184 | default: |
113 | break; | 185 | break; |
114 | } | 186 | } |
115 | } | 187 | } |
116 | 188 | ||
189 | void optc1_program_vupdate_interrupt( | ||
190 | struct timing_generator *optc, | ||
191 | const struct dc_crtc_timing *dc_crtc_timing) | ||
192 | { | ||
193 | struct optc *optc1 = DCN10TG_FROM_TG(optc); | ||
194 | int32_t vertical_line_start; | ||
195 | uint32_t asic_blank_end; | ||
196 | uint32_t vesa_sync_start; | ||
197 | struct dc_crtc_timing patched_crtc_timing; | ||
198 | |||
199 | patched_crtc_timing = *dc_crtc_timing; | ||
200 | optc1_apply_front_porch_workaround(optc, &patched_crtc_timing); | ||
201 | |||
202 | /* asic_h_blank_end = HsyncWidth + HbackPorch = | ||
203 | * vesa. usHorizontalTotal - vesa. usHorizontalSyncStart - | ||
204 | * vesa.h_left_border | ||
205 | */ | ||
206 | vesa_sync_start = patched_crtc_timing.h_addressable + | ||
207 | patched_crtc_timing.h_border_right + | ||
208 | patched_crtc_timing.h_front_porch; | ||
209 | |||
210 | asic_blank_end = patched_crtc_timing.h_total - | ||
211 | vesa_sync_start - | ||
212 | patched_crtc_timing.h_border_left; | ||
213 | |||
214 | /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, | ||
215 | * program the reg for interrupt postition. | ||
216 | */ | ||
217 | vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; | ||
218 | if (vertical_line_start < 0) | ||
219 | vertical_line_start = 0; | ||
220 | |||
221 | REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, | ||
222 | OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); | ||
223 | } | ||
224 | |||
117 | /** | 225 | /** |
118 | * program_timing_generator used by mode timing set | 226 | * program_timing_generator used by mode timing set |
119 | * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. | 227 | * Program CRTC Timing Registers - OTG_H_*, OTG_V_*, Pixel repetition. |
@@ -216,22 +324,14 @@ void optc1_program_timing( | |||
216 | patched_crtc_timing.v_addressable + | 324 | patched_crtc_timing.v_addressable + |
217 | patched_crtc_timing.v_border_bottom); | 325 | patched_crtc_timing.v_border_bottom); |
218 | 326 | ||
219 | REG_UPDATE_2(OTG_V_BLANK_START_END, | ||
220 | OTG_V_BLANK_START, asic_blank_start, | ||
221 | OTG_V_BLANK_END, asic_blank_end); | ||
222 | |||
223 | /* Use OTG_VERTICAL_INTERRUPT2 replace VUPDATE interrupt, | ||
224 | * program the reg for interrupt postition. | ||
225 | */ | ||
226 | vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; | 327 | vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1; |
227 | v_fp2 = 0; | 328 | v_fp2 = 0; |
228 | if (vertical_line_start < 0) | 329 | if (vertical_line_start < 0) |
229 | v_fp2 = -vertical_line_start; | 330 | v_fp2 = -vertical_line_start; |
230 | if (vertical_line_start < 0) | ||
231 | vertical_line_start = 0; | ||
232 | 331 | ||
233 | REG_SET(OTG_VERTICAL_INTERRUPT2_POSITION, 0, | 332 | REG_UPDATE_2(OTG_V_BLANK_START_END, |
234 | OTG_VERTICAL_INTERRUPT2_LINE_START, vertical_line_start); | 333 | OTG_V_BLANK_START, asic_blank_start, |
334 | OTG_V_BLANK_END, asic_blank_end); | ||
235 | 335 | ||
236 | /* v_sync polarity */ | 336 | /* v_sync polarity */ |
237 | v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? | 337 | v_sync_polarity = patched_crtc_timing.flags.VSYNC_POSITIVE_POLARITY ? |
@@ -290,7 +390,7 @@ void optc1_program_timing( | |||
290 | 390 | ||
291 | h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing); | 391 | h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing); |
292 | REG_UPDATE(OTG_H_TIMING_CNTL, | 392 | REG_UPDATE(OTG_H_TIMING_CNTL, |
293 | OTG_H_TIMING_DIV_BY2, h_div_2); | 393 | OTG_H_TIMING_DIV_BY2, h_div_2 || optc1->comb_opp_id != 0xf); |
294 | 394 | ||
295 | } | 395 | } |
296 | 396 | ||
@@ -1136,6 +1236,64 @@ bool optc1_is_stereo_left_eye(struct timing_generator *optc) | |||
1136 | return ret; | 1236 | return ret; |
1137 | } | 1237 | } |
1138 | 1238 | ||
1239 | bool optc1_is_matching_timing(struct timing_generator *tg, | ||
1240 | const struct dc_crtc_timing *otg_timing) | ||
1241 | { | ||
1242 | struct dc_crtc_timing hw_crtc_timing = {0}; | ||
1243 | struct dcn_otg_state s = {0}; | ||
1244 | |||
1245 | if (tg == NULL || otg_timing == NULL) | ||
1246 | return false; | ||
1247 | |||
1248 | optc1_read_otg_state(DCN10TG_FROM_TG(tg), &s); | ||
1249 | |||
1250 | hw_crtc_timing.h_total = s.h_total + 1; | ||
1251 | hw_crtc_timing.h_addressable = s.h_total - ((s.h_total - s.h_blank_start) + s.h_blank_end); | ||
1252 | hw_crtc_timing.h_front_porch = s.h_total + 1 - s.h_blank_start; | ||
1253 | hw_crtc_timing.h_sync_width = s.h_sync_a_end - s.h_sync_a_start; | ||
1254 | |||
1255 | hw_crtc_timing.v_total = s.v_total + 1; | ||
1256 | hw_crtc_timing.v_addressable = s.v_total - ((s.v_total - s.v_blank_start) + s.v_blank_end); | ||
1257 | hw_crtc_timing.v_front_porch = s.v_total + 1 - s.v_blank_start; | ||
1258 | hw_crtc_timing.v_sync_width = s.v_sync_a_end - s.v_sync_a_start; | ||
1259 | |||
1260 | if (otg_timing->h_total != hw_crtc_timing.h_total) | ||
1261 | return false; | ||
1262 | |||
1263 | if (otg_timing->h_border_left != hw_crtc_timing.h_border_left) | ||
1264 | return false; | ||
1265 | |||
1266 | if (otg_timing->h_addressable != hw_crtc_timing.h_addressable) | ||
1267 | return false; | ||
1268 | |||
1269 | if (otg_timing->h_border_right != hw_crtc_timing.h_border_right) | ||
1270 | return false; | ||
1271 | |||
1272 | if (otg_timing->h_front_porch != hw_crtc_timing.h_front_porch) | ||
1273 | return false; | ||
1274 | |||
1275 | if (otg_timing->h_sync_width != hw_crtc_timing.h_sync_width) | ||
1276 | return false; | ||
1277 | |||
1278 | if (otg_timing->v_total != hw_crtc_timing.v_total) | ||
1279 | return false; | ||
1280 | |||
1281 | if (otg_timing->v_border_top != hw_crtc_timing.v_border_top) | ||
1282 | return false; | ||
1283 | |||
1284 | if (otg_timing->v_addressable != hw_crtc_timing.v_addressable) | ||
1285 | return false; | ||
1286 | |||
1287 | if (otg_timing->v_border_bottom != hw_crtc_timing.v_border_bottom) | ||
1288 | return false; | ||
1289 | |||
1290 | if (otg_timing->v_sync_width != hw_crtc_timing.v_sync_width) | ||
1291 | return false; | ||
1292 | |||
1293 | return true; | ||
1294 | } | ||
1295 | |||
1296 | |||
1139 | void optc1_read_otg_state(struct optc *optc1, | 1297 | void optc1_read_otg_state(struct optc *optc1, |
1140 | struct dcn_otg_state *s) | 1298 | struct dcn_otg_state *s) |
1141 | { | 1299 | { |
@@ -1323,6 +1481,7 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { | |||
1323 | .validate_timing = optc1_validate_timing, | 1481 | .validate_timing = optc1_validate_timing, |
1324 | .program_timing = optc1_program_timing, | 1482 | .program_timing = optc1_program_timing, |
1325 | .program_vline_interrupt = optc1_program_vline_interrupt, | 1483 | .program_vline_interrupt = optc1_program_vline_interrupt, |
1484 | .program_vupdate_interrupt = optc1_program_vupdate_interrupt, | ||
1326 | .program_global_sync = optc1_program_global_sync, | 1485 | .program_global_sync = optc1_program_global_sync, |
1327 | .enable_crtc = optc1_enable_crtc, | 1486 | .enable_crtc = optc1_enable_crtc, |
1328 | .disable_crtc = optc1_disable_crtc, | 1487 | .disable_crtc = optc1_disable_crtc, |
@@ -1332,6 +1491,7 @@ static const struct timing_generator_funcs dcn10_tg_funcs = { | |||
1332 | .get_frame_count = optc1_get_vblank_counter, | 1491 | .get_frame_count = optc1_get_vblank_counter, |
1333 | .get_scanoutpos = optc1_get_crtc_scanoutpos, | 1492 | .get_scanoutpos = optc1_get_crtc_scanoutpos, |
1334 | .get_otg_active_size = optc1_get_otg_active_size, | 1493 | .get_otg_active_size = optc1_get_otg_active_size, |
1494 | .is_matching_timing = optc1_is_matching_timing, | ||
1335 | .set_early_control = optc1_set_early_control, | 1495 | .set_early_control = optc1_set_early_control, |
1336 | /* used by enable_timing_synchronization. Not need for FPGA */ | 1496 | /* used by enable_timing_synchronization. Not need for FPGA */ |
1337 | .wait_for_state = optc1_wait_for_state, | 1497 | .wait_for_state = optc1_wait_for_state, |
@@ -1371,10 +1531,13 @@ void dcn10_timing_generator_init(struct optc *optc1) | |||
1371 | optc1->min_v_blank_interlace = 5; | 1531 | optc1->min_v_blank_interlace = 5; |
1372 | optc1->min_h_sync_width = 8; | 1532 | optc1->min_h_sync_width = 8; |
1373 | optc1->min_v_sync_width = 1; | 1533 | optc1->min_v_sync_width = 1; |
1534 | optc1->comb_opp_id = 0xf; | ||
1374 | } | 1535 | } |
1375 | 1536 | ||
1376 | bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) | 1537 | bool optc1_is_two_pixels_per_containter(const struct dc_crtc_timing *timing) |
1377 | { | 1538 | { |
1378 | return timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; | 1539 | bool two_pix = timing->pixel_encoding == PIXEL_ENCODING_YCBCR420; |
1540 | |||
1541 | return two_pix; | ||
1379 | } | 1542 | } |
1380 | 1543 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 8eb71c0160a7..24452f11c598 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | |||
@@ -435,7 +435,7 @@ struct optc { | |||
435 | const struct dcn_optc_shift *tg_shift; | 435 | const struct dcn_optc_shift *tg_shift; |
436 | const struct dcn_optc_mask *tg_mask; | 436 | const struct dcn_optc_mask *tg_mask; |
437 | 437 | ||
438 | enum controller_id controller_id; | 438 | int comb_opp_id; |
439 | 439 | ||
440 | uint32_t max_h_total; | 440 | uint32_t max_h_total; |
441 | uint32_t max_v_total; | 441 | uint32_t max_v_total; |
@@ -483,9 +483,11 @@ void optc1_program_timing( | |||
483 | const struct dc_crtc_timing *dc_crtc_timing, | 483 | const struct dc_crtc_timing *dc_crtc_timing, |
484 | bool use_vbios); | 484 | bool use_vbios); |
485 | 485 | ||
486 | void optc1_program_vline_interrupt(struct timing_generator *optc, | 486 | void optc1_program_vline_interrupt( |
487 | struct timing_generator *optc, | ||
488 | const struct dc_crtc_timing *dc_crtc_timing, | ||
487 | enum vline_select vline, | 489 | enum vline_select vline, |
488 | struct vline_config vline_config); | 490 | const union vline_config *vline_config); |
489 | 491 | ||
490 | void optc1_program_global_sync( | 492 | void optc1_program_global_sync( |
491 | struct timing_generator *optc); | 493 | struct timing_generator *optc); |
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c index 1d1efd72b291..cf76ea2d9f5a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_base.c | |||
@@ -101,6 +101,18 @@ enum gpio_mode dal_gpio_get_mode( | |||
101 | return gpio->mode; | 101 | return gpio->mode; |
102 | } | 102 | } |
103 | 103 | ||
104 | enum gpio_result dal_gpio_lock_pin( | ||
105 | struct gpio *gpio) | ||
106 | { | ||
107 | return dal_gpio_service_lock(gpio->service, gpio->id, gpio->en); | ||
108 | } | ||
109 | |||
110 | enum gpio_result dal_gpio_unlock_pin( | ||
111 | struct gpio *gpio) | ||
112 | { | ||
113 | return dal_gpio_service_unlock(gpio->service, gpio->id, gpio->en); | ||
114 | } | ||
115 | |||
104 | enum gpio_result dal_gpio_change_mode( | 116 | enum gpio_result dal_gpio_change_mode( |
105 | struct gpio *gpio, | 117 | struct gpio *gpio, |
106 | enum gpio_mode mode) | 118 | enum gpio_mode mode) |
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index dada04296025..3c63a3c04dbb 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c | |||
@@ -192,6 +192,34 @@ static void set_pin_free( | |||
192 | service->busyness[id][en] = false; | 192 | service->busyness[id][en] = false; |
193 | } | 193 | } |
194 | 194 | ||
195 | enum gpio_result dal_gpio_service_lock( | ||
196 | struct gpio_service *service, | ||
197 | enum gpio_id id, | ||
198 | uint32_t en) | ||
199 | { | ||
200 | if (!service->busyness[id]) { | ||
201 | ASSERT_CRITICAL(false); | ||
202 | return GPIO_RESULT_OPEN_FAILED; | ||
203 | } | ||
204 | |||
205 | set_pin_busy(service, id, en); | ||
206 | return GPIO_RESULT_OK; | ||
207 | } | ||
208 | |||
209 | enum gpio_result dal_gpio_service_unlock( | ||
210 | struct gpio_service *service, | ||
211 | enum gpio_id id, | ||
212 | uint32_t en) | ||
213 | { | ||
214 | if (!service->busyness[id]) { | ||
215 | ASSERT_CRITICAL(false); | ||
216 | return GPIO_RESULT_OPEN_FAILED; | ||
217 | } | ||
218 | |||
219 | set_pin_free(service, id, en); | ||
220 | return GPIO_RESULT_OK; | ||
221 | } | ||
222 | |||
195 | enum gpio_result dal_gpio_service_open( | 223 | enum gpio_result dal_gpio_service_open( |
196 | struct gpio_service *service, | 224 | struct gpio_service *service, |
197 | enum gpio_id id, | 225 | enum gpio_id id, |
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h index 1d501a43d13b..0c678af75331 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.h | |||
@@ -52,4 +52,14 @@ void dal_gpio_service_close( | |||
52 | struct gpio_service *service, | 52 | struct gpio_service *service, |
53 | struct hw_gpio_pin **ptr); | 53 | struct hw_gpio_pin **ptr); |
54 | 54 | ||
55 | enum gpio_result dal_gpio_service_lock( | ||
56 | struct gpio_service *service, | ||
57 | enum gpio_id id, | ||
58 | uint32_t en); | ||
59 | |||
60 | enum gpio_result dal_gpio_service_unlock( | ||
61 | struct gpio_service *service, | ||
62 | enum gpio_id id, | ||
63 | uint32_t en); | ||
64 | |||
55 | #endif | 65 | #endif |
diff --git a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h index 43d1fbd8ace5..fe6301cb8681 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/clock_source.h +++ b/drivers/gpu/drm/amd/display/dc/inc/clock_source.h | |||
@@ -166,6 +166,10 @@ struct clock_source_funcs { | |||
166 | struct clock_source *, | 166 | struct clock_source *, |
167 | struct pixel_clk_params *, | 167 | struct pixel_clk_params *, |
168 | struct pll_settings *); | 168 | struct pll_settings *); |
169 | bool (*get_pixel_clk_frequency_100hz)( | ||
170 | struct clock_source *clock_source, | ||
171 | unsigned int inst, | ||
172 | unsigned int *pixel_clk_khz); | ||
169 | }; | 173 | }; |
170 | 174 | ||
171 | struct clock_source { | 175 | struct clock_source { |
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h index c20fdcaac53b..c9d3e37e9531 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h | |||
@@ -153,6 +153,7 @@ struct link_encoder_funcs { | |||
153 | void (*enable_hpd)(struct link_encoder *enc); | 153 | void (*enable_hpd)(struct link_encoder *enc); |
154 | void (*disable_hpd)(struct link_encoder *enc); | 154 | void (*disable_hpd)(struct link_encoder *enc); |
155 | bool (*is_dig_enabled)(struct link_encoder *enc); | 155 | bool (*is_dig_enabled)(struct link_encoder *enc); |
156 | unsigned int (*get_dig_frontend)(struct link_encoder *enc); | ||
156 | void (*destroy)(struct link_encoder **enc); | 157 | void (*destroy)(struct link_encoder **enc); |
157 | }; | 158 | }; |
158 | 159 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index df64cf73ceb9..03ae941895f3 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h | |||
@@ -134,7 +134,7 @@ struct dc_crtc_timing; | |||
134 | 134 | ||
135 | struct drr_params; | 135 | struct drr_params; |
136 | 136 | ||
137 | struct vline_config; | 137 | union vline_config; |
138 | 138 | ||
139 | 139 | ||
140 | enum vline_select { | 140 | enum vline_select { |
@@ -149,9 +149,14 @@ struct timing_generator_funcs { | |||
149 | void (*program_timing)(struct timing_generator *tg, | 149 | void (*program_timing)(struct timing_generator *tg, |
150 | const struct dc_crtc_timing *timing, | 150 | const struct dc_crtc_timing *timing, |
151 | bool use_vbios); | 151 | bool use_vbios); |
152 | void (*program_vline_interrupt)(struct timing_generator *optc, | 152 | void (*program_vline_interrupt)( |
153 | struct timing_generator *optc, | ||
154 | const struct dc_crtc_timing *dc_crtc_timing, | ||
153 | enum vline_select vline, | 155 | enum vline_select vline, |
154 | struct vline_config vline_config); | 156 | const union vline_config *vline_config); |
157 | |||
158 | void (*program_vupdate_interrupt)(struct timing_generator *optc, | ||
159 | const struct dc_crtc_timing *dc_crtc_timing); | ||
155 | bool (*enable_crtc)(struct timing_generator *tg); | 160 | bool (*enable_crtc)(struct timing_generator *tg); |
156 | bool (*disable_crtc)(struct timing_generator *tg); | 161 | bool (*disable_crtc)(struct timing_generator *tg); |
157 | bool (*is_counter_moving)(struct timing_generator *tg); | 162 | bool (*is_counter_moving)(struct timing_generator *tg); |
@@ -168,6 +173,8 @@ struct timing_generator_funcs { | |||
168 | bool (*get_otg_active_size)(struct timing_generator *optc, | 173 | bool (*get_otg_active_size)(struct timing_generator *optc, |
169 | uint32_t *otg_active_width, | 174 | uint32_t *otg_active_width, |
170 | uint32_t *otg_active_height); | 175 | uint32_t *otg_active_height); |
176 | bool (*is_matching_timing)(struct timing_generator *tg, | ||
177 | const struct dc_crtc_timing *otg_timing); | ||
171 | void (*set_early_control)(struct timing_generator *tg, | 178 | void (*set_early_control)(struct timing_generator *tg, |
172 | uint32_t early_cntl); | 179 | uint32_t early_cntl); |
173 | void (*wait_for_state)(struct timing_generator *tg, | 180 | void (*wait_for_state)(struct timing_generator *tg, |
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index d6a85f48b6d1..341b4810288c 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | |||
@@ -70,6 +70,8 @@ struct hw_sequencer_funcs { | |||
70 | 70 | ||
71 | void (*init_hw)(struct dc *dc); | 71 | void (*init_hw)(struct dc *dc); |
72 | 72 | ||
73 | void (*init_pipes)(struct dc *dc, struct dc_state *context); | ||
74 | |||
73 | enum dc_status (*apply_ctx_to_hw)( | 75 | enum dc_status (*apply_ctx_to_hw)( |
74 | struct dc *dc, struct dc_state *context); | 76 | struct dc *dc, struct dc_state *context); |
75 | 77 | ||
diff --git a/drivers/gpu/drm/amd/display/dc/inc/vm_helper.h b/drivers/gpu/drm/amd/display/dc/inc/vm_helper.h index a202206e22a3..193407f76a80 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/vm_helper.h +++ b/drivers/gpu/drm/amd/display/dc/inc/vm_helper.h | |||
@@ -39,8 +39,8 @@ struct vm_helper { | |||
39 | unsigned int num_vmid; | 39 | unsigned int num_vmid; |
40 | unsigned int num_hubp; | 40 | unsigned int num_hubp; |
41 | unsigned int num_vmids_available; | 41 | unsigned int num_vmids_available; |
42 | uint64_t *ptb_assigned_to_vmid; | 42 | uint64_t ptb_assigned_to_vmid[MAX_VMID]; |
43 | struct vmid_usage *hubp_vmid_usage; | 43 | struct vmid_usage hubp_vmid_usage[MAX_HUBP]; |
44 | }; | 44 | }; |
45 | 45 | ||
46 | uint8_t get_vmid_for_ptb( | 46 | uint8_t get_vmid_for_ptb( |
@@ -48,7 +48,8 @@ uint8_t get_vmid_for_ptb( | |||
48 | int64_t ptb, | 48 | int64_t ptb, |
49 | uint8_t pipe_idx); | 49 | uint8_t pipe_idx); |
50 | 50 | ||
51 | struct vm_helper init_vm_helper( | 51 | void init_vm_helper( |
52 | struct vm_helper *vm_helper, | ||
52 | unsigned int num_vmid, | 53 | unsigned int num_vmid, |
53 | unsigned int num_hubp); | 54 | unsigned int num_hubp); |
54 | 55 | ||
diff --git a/drivers/gpu/drm/amd/display/include/gpio_interface.h b/drivers/gpu/drm/amd/display/include/gpio_interface.h index e4fd31024b92..7de64195dc33 100644 --- a/drivers/gpu/drm/amd/display/include/gpio_interface.h +++ b/drivers/gpu/drm/amd/display/include/gpio_interface.h | |||
@@ -59,6 +59,14 @@ enum gpio_result dal_gpio_change_mode( | |||
59 | struct gpio *gpio, | 59 | struct gpio *gpio, |
60 | enum gpio_mode mode); | 60 | enum gpio_mode mode); |
61 | 61 | ||
62 | /* Lock Pin */ | ||
63 | enum gpio_result dal_gpio_lock_pin( | ||
64 | struct gpio *gpio); | ||
65 | |||
66 | /* Unlock Pin */ | ||
67 | enum gpio_result dal_gpio_unlock_pin( | ||
68 | struct gpio *gpio); | ||
69 | |||
62 | /* Get the GPIO id */ | 70 | /* Get the GPIO id */ |
63 | enum gpio_id dal_gpio_get_id( | 71 | enum gpio_id dal_gpio_get_id( |
64 | const struct gpio *gpio); | 72 | const struct gpio *gpio); |
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c index eefb85928298..0fbc8fbc3541 100644 --- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c +++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c | |||
@@ -1765,68 +1765,85 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, | |||
1765 | { | 1765 | { |
1766 | struct dc_transfer_func_distributed_points *tf_pts = &input_tf->tf_pts; | 1766 | struct dc_transfer_func_distributed_points *tf_pts = &input_tf->tf_pts; |
1767 | struct dividers dividers; | 1767 | struct dividers dividers; |
1768 | |||
1769 | struct pwl_float_data *rgb_user = NULL; | 1768 | struct pwl_float_data *rgb_user = NULL; |
1770 | struct pwl_float_data_ex *curve = NULL; | 1769 | struct pwl_float_data_ex *curve = NULL; |
1771 | struct gamma_pixel *axis_x = NULL; | 1770 | struct gamma_pixel *axis_x = NULL; |
1772 | struct pixel_gamma_point *coeff = NULL; | 1771 | struct pixel_gamma_point *coeff = NULL; |
1773 | enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; | 1772 | enum dc_transfer_func_predefined tf = TRANSFER_FUNCTION_SRGB; |
1773 | uint32_t i; | ||
1774 | bool ret = false; | 1774 | bool ret = false; |
1775 | 1775 | ||
1776 | if (input_tf->type == TF_TYPE_BYPASS) | 1776 | if (input_tf->type == TF_TYPE_BYPASS) |
1777 | return false; | 1777 | return false; |
1778 | 1778 | ||
1779 | /* we can use hardcoded curve for plain SRGB TF */ | 1779 | /* we can use hardcoded curve for plain SRGB TF |
1780 | * If linear, it's bypass if on user ramp | ||
1781 | */ | ||
1780 | if (input_tf->type == TF_TYPE_PREDEFINED && | 1782 | if (input_tf->type == TF_TYPE_PREDEFINED && |
1781 | input_tf->tf == TRANSFER_FUNCTION_SRGB && | 1783 | (input_tf->tf == TRANSFER_FUNCTION_SRGB || |
1782 | !mapUserRamp) | 1784 | input_tf->tf == TRANSFER_FUNCTION_LINEAR) && |
1785 | !mapUserRamp) | ||
1783 | return true; | 1786 | return true; |
1784 | 1787 | ||
1785 | input_tf->type = TF_TYPE_DISTRIBUTED_POINTS; | 1788 | input_tf->type = TF_TYPE_DISTRIBUTED_POINTS; |
1786 | 1789 | ||
1787 | rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS, | 1790 | if (mapUserRamp && ramp && ramp->type == GAMMA_RGB_256) { |
1788 | sizeof(*rgb_user), | 1791 | rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS, |
1789 | GFP_KERNEL); | 1792 | sizeof(*rgb_user), |
1790 | if (!rgb_user) | 1793 | GFP_KERNEL); |
1791 | goto rgb_user_alloc_fail; | 1794 | if (!rgb_user) |
1795 | goto rgb_user_alloc_fail; | ||
1796 | |||
1797 | axis_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axis_x), | ||
1798 | GFP_KERNEL); | ||
1799 | if (!axis_x) | ||
1800 | goto axis_x_alloc_fail; | ||
1801 | |||
1802 | dividers.divider1 = dc_fixpt_from_fraction(3, 2); | ||
1803 | dividers.divider2 = dc_fixpt_from_int(2); | ||
1804 | dividers.divider3 = dc_fixpt_from_fraction(5, 2); | ||
1805 | |||
1806 | build_evenly_distributed_points( | ||
1807 | axis_x, | ||
1808 | ramp->num_entries, | ||
1809 | dividers); | ||
1810 | |||
1811 | scale_gamma(rgb_user, ramp, dividers); | ||
1812 | } | ||
1813 | |||
1792 | curve = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*curve), | 1814 | curve = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*curve), |
1793 | GFP_KERNEL); | 1815 | GFP_KERNEL); |
1794 | if (!curve) | 1816 | if (!curve) |
1795 | goto curve_alloc_fail; | 1817 | goto curve_alloc_fail; |
1796 | axis_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axis_x), | 1818 | |
1797 | GFP_KERNEL); | ||
1798 | if (!axis_x) | ||
1799 | goto axis_x_alloc_fail; | ||
1800 | coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff), | 1819 | coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff), |
1801 | GFP_KERNEL); | 1820 | GFP_KERNEL); |
1802 | if (!coeff) | 1821 | if (!coeff) |
1803 | goto coeff_alloc_fail; | 1822 | goto coeff_alloc_fail; |
1804 | 1823 | ||
1805 | dividers.divider1 = dc_fixpt_from_fraction(3, 2); | ||
1806 | dividers.divider2 = dc_fixpt_from_int(2); | ||
1807 | dividers.divider3 = dc_fixpt_from_fraction(5, 2); | ||
1808 | |||
1809 | tf = input_tf->tf; | 1824 | tf = input_tf->tf; |
1810 | 1825 | ||
1811 | build_evenly_distributed_points( | ||
1812 | axis_x, | ||
1813 | ramp->num_entries, | ||
1814 | dividers); | ||
1815 | |||
1816 | if (ramp->type == GAMMA_RGB_256 && mapUserRamp) | ||
1817 | scale_gamma(rgb_user, ramp, dividers); | ||
1818 | else if (ramp->type == GAMMA_RGB_FLOAT_1024) | ||
1819 | scale_gamma_dx(rgb_user, ramp, dividers); | ||
1820 | |||
1821 | if (tf == TRANSFER_FUNCTION_PQ) | 1826 | if (tf == TRANSFER_FUNCTION_PQ) |
1822 | build_de_pq(curve, | 1827 | build_de_pq(curve, |
1823 | MAX_HW_POINTS, | 1828 | MAX_HW_POINTS, |
1824 | coordinates_x); | 1829 | coordinates_x); |
1825 | else | 1830 | else if (tf == TRANSFER_FUNCTION_SRGB || |
1831 | tf == TRANSFER_FUNCTION_BT709) | ||
1826 | build_degamma(curve, | 1832 | build_degamma(curve, |
1827 | MAX_HW_POINTS, | 1833 | MAX_HW_POINTS, |
1828 | coordinates_x, | 1834 | coordinates_x, |
1829 | tf == TRANSFER_FUNCTION_SRGB ? true:false); | 1835 | tf == TRANSFER_FUNCTION_SRGB ? true : false); |
1836 | else if (tf == TRANSFER_FUNCTION_LINEAR) { | ||
1837 | // just copy coordinates_x into curve | ||
1838 | i = 0; | ||
1839 | while (i != MAX_HW_POINTS + 1) { | ||
1840 | curve[i].r = coordinates_x[i].x; | ||
1841 | curve[i].g = curve[i].r; | ||
1842 | curve[i].b = curve[i].r; | ||
1843 | i++; | ||
1844 | } | ||
1845 | } else | ||
1846 | goto invalid_tf_fail; | ||
1830 | 1847 | ||
1831 | tf_pts->end_exponent = 0; | 1848 | tf_pts->end_exponent = 0; |
1832 | tf_pts->x_point_at_y1_red = 1; | 1849 | tf_pts->x_point_at_y1_red = 1; |
@@ -1836,23 +1853,21 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf, | |||
1836 | map_regamma_hw_to_x_user(ramp, coeff, rgb_user, | 1853 | map_regamma_hw_to_x_user(ramp, coeff, rgb_user, |
1837 | coordinates_x, axis_x, curve, | 1854 | coordinates_x, axis_x, curve, |
1838 | MAX_HW_POINTS, tf_pts, | 1855 | MAX_HW_POINTS, tf_pts, |
1839 | mapUserRamp && ramp->type != GAMMA_CUSTOM); | 1856 | mapUserRamp && ramp && ramp->type == GAMMA_RGB_256); |
1840 | if (ramp->type == GAMMA_CUSTOM) | ||
1841 | apply_lut_1d(ramp, MAX_HW_POINTS, tf_pts); | ||
1842 | 1857 | ||
1843 | ret = true; | 1858 | ret = true; |
1844 | 1859 | ||
1860 | invalid_tf_fail: | ||
1845 | kvfree(coeff); | 1861 | kvfree(coeff); |
1846 | coeff_alloc_fail: | 1862 | coeff_alloc_fail: |
1847 | kvfree(axis_x); | ||
1848 | axis_x_alloc_fail: | ||
1849 | kvfree(curve); | 1863 | kvfree(curve); |
1850 | curve_alloc_fail: | 1864 | curve_alloc_fail: |
1865 | kvfree(axis_x); | ||
1866 | axis_x_alloc_fail: | ||
1851 | kvfree(rgb_user); | 1867 | kvfree(rgb_user); |
1852 | rgb_user_alloc_fail: | 1868 | rgb_user_alloc_fail: |
1853 | 1869 | ||
1854 | return ret; | 1870 | return ret; |
1855 | |||
1856 | } | 1871 | } |
1857 | 1872 | ||
1858 | 1873 | ||
diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index baab6c4ae191..3ba87b076287 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c | |||
@@ -47,10 +47,10 @@ static const unsigned char min_reduction_table_v_2_2[13] = { | |||
47 | 47 | ||
48 | /* Possible ABM 2.2 Max Reduction configs from least aggressive to most aggressive | 48 | /* Possible ABM 2.2 Max Reduction configs from least aggressive to most aggressive |
49 | * 0 1 2 3 4 5 6 7 8 9 10 11 12 | 49 | * 0 1 2 3 4 5 6 7 8 9 10 11 12 |
50 | * 96.1 89.8 85.1 80.3 69.4 64.7 54.9 45.1 30.2 25.1 19.6 12.5 12.5 % | 50 | * 96.1 89.8 74.9 69.4 64.7 52.2 48.6 39.6 30.2 25.1 19.6 12.5 12.5 % |
51 | */ | 51 | */ |
52 | static const unsigned char max_reduction_table_v_2_2[13] = { | 52 | static const unsigned char max_reduction_table_v_2_2[13] = { |
53 | 0xf5, 0xe5, 0xd9, 0xcd, 0xb1, 0xa5, 0x8c, 0x73, 0x4d, 0x40, 0x32, 0x20, 0x20}; | 53 | 0xf5, 0xe5, 0xbf, 0xb1, 0xa5, 0x85, 0x7c, 0x65, 0x4d, 0x40, 0x32, 0x20, 0x20}; |
54 | 54 | ||
55 | /* Predefined ABM configuration sets. We may have different configuration sets | 55 | /* Predefined ABM configuration sets. We may have different configuration sets |
56 | * in order to satisfy different power/quality requirements. | 56 | * in order to satisfy different power/quality requirements. |
@@ -67,9 +67,14 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le | |||
67 | #define NUM_AGGR_LEVEL 4 | 67 | #define NUM_AGGR_LEVEL 4 |
68 | #define NUM_POWER_FN_SEGS 8 | 68 | #define NUM_POWER_FN_SEGS 8 |
69 | #define NUM_BL_CURVE_SEGS 16 | 69 | #define NUM_BL_CURVE_SEGS 16 |
70 | #define IRAM_RESERVE_AREA_START 0xF0 // reserve 0xF0~0xFF are write by DMCU only | ||
71 | #define IRAM_SIZE 256 | 70 | #define IRAM_SIZE 256 |
72 | 71 | ||
72 | #define IRAM_RESERVE_AREA_START_V2 0xF0 // reserve 0xF0~0xF6 are write by DMCU only | ||
73 | #define IRAM_RESERVE_AREA_END_V2 0xF6 // reserve 0xF0~0xF6 are write by DMCU only | ||
74 | |||
75 | #define IRAM_RESERVE_AREA_START_V2_2 0xF0 // reserve 0xF0~0xFF are write by DMCU only | ||
76 | #define IRAM_RESERVE_AREA_END_V2_2 0xFF // reserve 0xF0~0xFF are write by DMCU only | ||
77 | |||
73 | #pragma pack(push, 1) | 78 | #pragma pack(push, 1) |
74 | /* NOTE: iRAM is 256B in size */ | 79 | /* NOTE: iRAM is 256B in size */ |
75 | struct iram_table_v_2 { | 80 | struct iram_table_v_2 { |
@@ -148,8 +153,10 @@ struct iram_table_v_2_2 { | |||
148 | uint16_t dmcu_version; /* 0xf4 */ | 153 | uint16_t dmcu_version; /* 0xf4 */ |
149 | uint8_t dmcu_state; /* 0xf6 */ | 154 | uint8_t dmcu_state; /* 0xf6 */ |
150 | 155 | ||
151 | uint16_t blRampReduction; /* 0xf7 */ | 156 | uint8_t dummy1; /* 0xf7 */ |
152 | uint16_t blRampStart; /* 0xf9 */ | 157 | uint8_t dummy2; /* 0xf8 */ |
158 | uint8_t dummy3; /* 0xf9 */ | ||
159 | uint8_t dummy4; /* 0xfa */ | ||
153 | uint8_t dummy5; /* 0xfb */ | 160 | uint8_t dummy5; /* 0xfb */ |
154 | uint8_t dummy6; /* 0xfc */ | 161 | uint8_t dummy6; /* 0xfc */ |
155 | uint8_t dummy7; /* 0xfd */ | 162 | uint8_t dummy7; /* 0xfd */ |
@@ -420,11 +427,6 @@ void fill_iram_v_2_2(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame | |||
420 | ram_table->deviation_gain[2] = 0xb3; | 427 | ram_table->deviation_gain[2] = 0xb3; |
421 | ram_table->deviation_gain[3] = 0xb3; | 428 | ram_table->deviation_gain[3] = 0xb3; |
422 | 429 | ||
423 | ram_table->blRampReduction = | ||
424 | cpu_to_be16(params.backlight_ramping_reduction); | ||
425 | ram_table->blRampStart = | ||
426 | cpu_to_be16(params.backlight_ramping_start); | ||
427 | |||
428 | ram_table->min_reduction[0][0] = min_reduction_table_v_2_2[abm_config[set][0]]; | 430 | ram_table->min_reduction[0][0] = min_reduction_table_v_2_2[abm_config[set][0]]; |
429 | ram_table->min_reduction[1][0] = min_reduction_table_v_2_2[abm_config[set][0]]; | 431 | ram_table->min_reduction[1][0] = min_reduction_table_v_2_2[abm_config[set][0]]; |
430 | ram_table->min_reduction[2][0] = min_reduction_table_v_2_2[abm_config[set][0]]; | 432 | ram_table->min_reduction[2][0] = min_reduction_table_v_2_2[abm_config[set][0]]; |
@@ -561,6 +563,7 @@ bool dmcu_load_iram(struct dmcu *dmcu, | |||
561 | struct dmcu_iram_parameters params) | 563 | struct dmcu_iram_parameters params) |
562 | { | 564 | { |
563 | unsigned char ram_table[IRAM_SIZE]; | 565 | unsigned char ram_table[IRAM_SIZE]; |
566 | bool result = false; | ||
564 | 567 | ||
565 | if (dmcu == NULL) | 568 | if (dmcu == NULL) |
566 | return false; | 569 | return false; |
@@ -572,10 +575,21 @@ bool dmcu_load_iram(struct dmcu *dmcu, | |||
572 | 575 | ||
573 | if (dmcu->dmcu_version.abm_version == 0x22) { | 576 | if (dmcu->dmcu_version.abm_version == 0x22) { |
574 | fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params); | 577 | fill_iram_v_2_2((struct iram_table_v_2_2 *)ram_table, params); |
578 | |||
579 | result = dmcu->funcs->load_iram( | ||
580 | dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2_2); | ||
575 | } else { | 581 | } else { |
576 | fill_iram_v_2((struct iram_table_v_2 *)ram_table, params); | 582 | fill_iram_v_2((struct iram_table_v_2 *)ram_table, params); |
583 | |||
584 | result = dmcu->funcs->load_iram( | ||
585 | dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START_V2); | ||
586 | |||
587 | if (result) | ||
588 | result = dmcu->funcs->load_iram( | ||
589 | dmcu, IRAM_RESERVE_AREA_END_V2 + 1, | ||
590 | (char *)(&ram_table) + IRAM_RESERVE_AREA_END_V2 + 1, | ||
591 | sizeof(ram_table) - IRAM_RESERVE_AREA_END_V2 - 1); | ||
577 | } | 592 | } |
578 | 593 | ||
579 | return dmcu->funcs->load_iram( | 594 | return result; |
580 | dmcu, 0, (char *)(&ram_table), IRAM_RESERVE_AREA_START); | ||
581 | } | 595 | } |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 0d38ac2fdbf1..5479125ff4f6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | |||
@@ -3579,6 +3579,10 @@ static int vega10_generate_dpm_level_enable_mask( | |||
3579 | vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); | 3579 | vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); |
3580 | data->smc_state_table.mem_max_level = | 3580 | data->smc_state_table.mem_max_level = |
3581 | vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); | 3581 | vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); |
3582 | data->smc_state_table.soc_boot_level = | ||
3583 | vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table)); | ||
3584 | data->smc_state_table.soc_max_level = | ||
3585 | vega10_find_highest_dpm_level(&(data->dpm_table.soc_table)); | ||
3582 | 3586 | ||
3583 | PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), | 3587 | PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), |
3584 | "Attempt to upload DPM Bootup Levels Failed!", | 3588 | "Attempt to upload DPM Bootup Levels Failed!", |
@@ -3593,6 +3597,9 @@ static int vega10_generate_dpm_level_enable_mask( | |||
3593 | for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++) | 3597 | for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++) |
3594 | data->dpm_table.mem_table.dpm_levels[i].enabled = true; | 3598 | data->dpm_table.mem_table.dpm_levels[i].enabled = true; |
3595 | 3599 | ||
3600 | for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++) | ||
3601 | data->dpm_table.soc_table.dpm_levels[i].enabled = true; | ||
3602 | |||
3596 | return 0; | 3603 | return 0; |
3597 | } | 3604 | } |
3598 | 3605 | ||
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index da022ca79b56..0769b1ec562b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | |||
@@ -771,40 +771,47 @@ static int vega20_init_smc_table(struct pp_hwmgr *hwmgr) | |||
771 | return 0; | 771 | return 0; |
772 | } | 772 | } |
773 | 773 | ||
774 | /* | ||
775 | * Override PCIe link speed and link width for DPM Level 1. PPTable entries | ||
776 | * reflect the ASIC capabilities and not the system capabilities. For e.g. | ||
777 | * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch | ||
778 | * to DPM1, it fails as system doesn't support Gen4. | ||
779 | */ | ||
774 | static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr) | 780 | static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr) |
775 | { | 781 | { |
776 | struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); | 782 | struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); |
777 | uint32_t pcie_speed = 0, pcie_width = 0, pcie_arg; | 783 | uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg; |
778 | int ret; | 784 | int ret; |
779 | 785 | ||
780 | if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) | 786 | if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) |
781 | pcie_speed = 16; | 787 | pcie_gen = 3; |
782 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) | 788 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) |
783 | pcie_speed = 8; | 789 | pcie_gen = 2; |
784 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) | 790 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) |
785 | pcie_speed = 5; | 791 | pcie_gen = 1; |
786 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) | 792 | else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) |
787 | pcie_speed = 2; | 793 | pcie_gen = 0; |
788 | 794 | ||
789 | if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X32) | 795 | if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) |
790 | pcie_width = 32; | 796 | pcie_width = 6; |
791 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) | ||
792 | pcie_width = 16; | ||
793 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) | 797 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) |
794 | pcie_width = 12; | 798 | pcie_width = 5; |
795 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) | 799 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) |
796 | pcie_width = 8; | ||
797 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) | ||
798 | pcie_width = 4; | 800 | pcie_width = 4; |
801 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) | ||
802 | pcie_width = 3; | ||
799 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) | 803 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) |
800 | pcie_width = 2; | 804 | pcie_width = 2; |
801 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) | 805 | else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) |
802 | pcie_width = 1; | 806 | pcie_width = 1; |
803 | 807 | ||
804 | pcie_arg = pcie_width | (pcie_speed << 8); | 808 | /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 |
805 | 809 | * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 | |
810 | * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 | ||
811 | */ | ||
812 | smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width; | ||
806 | ret = smum_send_msg_to_smc_with_parameter(hwmgr, | 813 | ret = smum_send_msg_to_smc_with_parameter(hwmgr, |
807 | PPSMC_MSG_OverridePcieParameters, pcie_arg); | 814 | PPSMC_MSG_OverridePcieParameters, smu_pcie_arg); |
808 | PP_ASSERT_WITH_CODE(!ret, | 815 | PP_ASSERT_WITH_CODE(!ret, |
809 | "[OverridePcieParameters] Attempt to override pcie params failed!", | 816 | "[OverridePcieParameters] Attempt to override pcie params failed!", |
810 | return ret); | 817 | return ret); |
@@ -1611,11 +1618,6 @@ static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) | |||
1611 | "[EnableDPMTasks] Failed to initialize SMC table!", | 1618 | "[EnableDPMTasks] Failed to initialize SMC table!", |
1612 | return result); | 1619 | return result); |
1613 | 1620 | ||
1614 | result = vega20_override_pcie_parameters(hwmgr); | ||
1615 | PP_ASSERT_WITH_CODE(!result, | ||
1616 | "[EnableDPMTasks] Failed to override pcie parameters!", | ||
1617 | return result); | ||
1618 | |||
1619 | result = vega20_run_btc(hwmgr); | 1621 | result = vega20_run_btc(hwmgr); |
1620 | PP_ASSERT_WITH_CODE(!result, | 1622 | PP_ASSERT_WITH_CODE(!result, |
1621 | "[EnableDPMTasks] Failed to run btc!", | 1623 | "[EnableDPMTasks] Failed to run btc!", |
@@ -1631,6 +1633,11 @@ static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) | |||
1631 | "[EnableDPMTasks] Failed to enable all smu features!", | 1633 | "[EnableDPMTasks] Failed to enable all smu features!", |
1632 | return result); | 1634 | return result); |
1633 | 1635 | ||
1636 | result = vega20_override_pcie_parameters(hwmgr); | ||
1637 | PP_ASSERT_WITH_CODE(!result, | ||
1638 | "[EnableDPMTasks] Failed to override pcie parameters!", | ||
1639 | return result); | ||
1640 | |||
1634 | result = vega20_notify_smc_display_change(hwmgr); | 1641 | result = vega20_notify_smc_display_change(hwmgr); |
1635 | PP_ASSERT_WITH_CODE(!result, | 1642 | PP_ASSERT_WITH_CODE(!result, |
1636 | "[EnableDPMTasks] Failed to notify smc display change!", | 1643 | "[EnableDPMTasks] Failed to notify smc display change!", |