diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2018-07-25 16:11:34 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-07-27 10:07:44 -0400 |
commit | f1e582ebfd703ea01dc4caf4d339b7c84ec3ff29 (patch) | |
tree | 56bfd3cd4840cf6dee41cbbf77d468823065872b /drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | |
parent | d04cc604a66b07eff8fce824fb6c0fdc0875d2e3 (diff) |
drm/amdgpu: implement harvesting support for UVD 7.2 (v3)
Properly handle cases where one or more instance of the IP
block may be harvested.
v2: make sure ip_num_rings is initialized amdgpu_queue_mgr.c
v3: rebase on Christian's UVD changes, drop unused var
Reviewed-by: James Zhu <James.Zhu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index d74c1b242667..5fab3560a71d 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | |||
@@ -41,6 +41,12 @@ | |||
41 | #include "mmhub/mmhub_1_0_sh_mask.h" | 41 | #include "mmhub/mmhub_1_0_sh_mask.h" |
42 | #include "ivsrcid/uvd/irqsrcs_uvd_7_0.h" | 42 | #include "ivsrcid/uvd/irqsrcs_uvd_7_0.h" |
43 | 43 | ||
44 | #define mmUVD_PG0_CC_UVD_HARVESTING 0x00c7 | ||
45 | #define mmUVD_PG0_CC_UVD_HARVESTING_BASE_IDX 1 | ||
46 | //UVD_PG0_CC_UVD_HARVESTING | ||
47 | #define UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE__SHIFT 0x1 | ||
48 | #define UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK 0x00000002L | ||
49 | |||
44 | #define UVD7_MAX_HW_INSTANCES_VEGA20 2 | 50 | #define UVD7_MAX_HW_INSTANCES_VEGA20 2 |
45 | 51 | ||
46 | static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev); | 52 | static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev); |
@@ -370,10 +376,25 @@ error: | |||
370 | static int uvd_v7_0_early_init(void *handle) | 376 | static int uvd_v7_0_early_init(void *handle) |
371 | { | 377 | { |
372 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 378 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
373 | if (adev->asic_type == CHIP_VEGA20) | 379 | |
380 | if (adev->asic_type == CHIP_VEGA20) { | ||
381 | u32 harvest; | ||
382 | int i; | ||
383 | |||
374 | adev->uvd.num_uvd_inst = UVD7_MAX_HW_INSTANCES_VEGA20; | 384 | adev->uvd.num_uvd_inst = UVD7_MAX_HW_INSTANCES_VEGA20; |
375 | else | 385 | for (i = 0; i < adev->uvd.num_uvd_inst; i++) { |
386 | harvest = RREG32_SOC15(UVD, i, mmUVD_PG0_CC_UVD_HARVESTING); | ||
387 | if (harvest & UVD_PG0_CC_UVD_HARVESTING__UVD_DISABLE_MASK) { | ||
388 | adev->uvd.harvest_config |= 1 << i; | ||
389 | } | ||
390 | } | ||
391 | if (adev->uvd.harvest_config == (AMDGPU_UVD_HARVEST_UVD0 | | ||
392 | AMDGPU_UVD_HARVEST_UVD1)) | ||
393 | /* both instances are harvested, disable the block */ | ||
394 | return -ENOENT; | ||
395 | } else { | ||
376 | adev->uvd.num_uvd_inst = 1; | 396 | adev->uvd.num_uvd_inst = 1; |
397 | } | ||
377 | 398 | ||
378 | if (amdgpu_sriov_vf(adev)) | 399 | if (amdgpu_sriov_vf(adev)) |
379 | adev->uvd.num_enc_rings = 1; | 400 | adev->uvd.num_enc_rings = 1; |
@@ -393,6 +414,8 @@ static int uvd_v7_0_sw_init(void *handle) | |||
393 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 414 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
394 | 415 | ||
395 | for (j = 0; j < adev->uvd.num_uvd_inst; j++) { | 416 | for (j = 0; j < adev->uvd.num_uvd_inst; j++) { |
417 | if (adev->uvd.harvest_config & (1 << j)) | ||
418 | continue; | ||
396 | /* UVD TRAP */ | 419 | /* UVD TRAP */ |
397 | r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_uvds[j], UVD_7_0__SRCID__UVD_SYSTEM_MESSAGE_INTERRUPT, &adev->uvd.inst[j].irq); | 420 | r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_uvds[j], UVD_7_0__SRCID__UVD_SYSTEM_MESSAGE_INTERRUPT, &adev->uvd.inst[j].irq); |
398 | if (r) | 421 | if (r) |
@@ -425,6 +448,8 @@ static int uvd_v7_0_sw_init(void *handle) | |||
425 | return r; | 448 | return r; |
426 | 449 | ||
427 | for (j = 0; j < adev->uvd.num_uvd_inst; j++) { | 450 | for (j = 0; j < adev->uvd.num_uvd_inst; j++) { |
451 | if (adev->uvd.harvest_config & (1 << j)) | ||
452 | continue; | ||
428 | if (!amdgpu_sriov_vf(adev)) { | 453 | if (!amdgpu_sriov_vf(adev)) { |
429 | ring = &adev->uvd.inst[j].ring; | 454 | ring = &adev->uvd.inst[j].ring; |
430 | sprintf(ring->name, "uvd<%d>", j); | 455 | sprintf(ring->name, "uvd<%d>", j); |
@@ -472,6 +497,8 @@ static int uvd_v7_0_sw_fini(void *handle) | |||
472 | return r; | 497 | return r; |
473 | 498 | ||
474 | for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { | 499 | for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { |
500 | if (adev->uvd.harvest_config & (1 << j)) | ||
501 | continue; | ||
475 | for (i = 0; i < adev->uvd.num_enc_rings; ++i) | 502 | for (i = 0; i < adev->uvd.num_enc_rings; ++i) |
476 | amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]); | 503 | amdgpu_ring_fini(&adev->uvd.inst[j].ring_enc[i]); |
477 | } | 504 | } |
@@ -500,6 +527,8 @@ static int uvd_v7_0_hw_init(void *handle) | |||
500 | goto done; | 527 | goto done; |
501 | 528 | ||
502 | for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { | 529 | for (j = 0; j < adev->uvd.num_uvd_inst; ++j) { |
530 | if (adev->uvd.harvest_config & (1 << j)) | ||
531 | continue; | ||
503 | ring = &adev->uvd.inst[j].ring; | 532 | ring = &adev->uvd.inst[j].ring; |
504 | 533 | ||
505 | if (!amdgpu_sriov_vf(adev)) { | 534 | if (!amdgpu_sriov_vf(adev)) { |
@@ -579,8 +608,11 @@ static int uvd_v7_0_hw_fini(void *handle) | |||
579 | DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); | 608 | DRM_DEBUG("For SRIOV client, shouldn't do anything.\n"); |
580 | } | 609 | } |
581 | 610 | ||
582 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) | 611 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { |
612 | if (adev->uvd.harvest_config & (1 << i)) | ||
613 | continue; | ||
583 | adev->uvd.inst[i].ring.ready = false; | 614 | adev->uvd.inst[i].ring.ready = false; |
615 | } | ||
584 | 616 | ||
585 | return 0; | 617 | return 0; |
586 | } | 618 | } |
@@ -623,6 +655,8 @@ static void uvd_v7_0_mc_resume(struct amdgpu_device *adev) | |||
623 | int i; | 655 | int i; |
624 | 656 | ||
625 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { | 657 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { |
658 | if (adev->uvd.harvest_config & (1 << i)) | ||
659 | continue; | ||
626 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { | 660 | if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { |
627 | WREG32_SOC15(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, | 661 | WREG32_SOC15(UVD, i, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW, |
628 | lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr)); | 662 | lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr)); |
@@ -695,6 +729,8 @@ static int uvd_v7_0_mmsch_start(struct amdgpu_device *adev, | |||
695 | WREG32_SOC15(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP, 0); | 729 | WREG32_SOC15(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP, 0); |
696 | 730 | ||
697 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { | 731 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { |
732 | if (adev->uvd.harvest_config & (1 << i)) | ||
733 | continue; | ||
698 | WDOORBELL32(adev->uvd.inst[i].ring_enc[0].doorbell_index, 0); | 734 | WDOORBELL32(adev->uvd.inst[i].ring_enc[0].doorbell_index, 0); |
699 | adev->wb.wb[adev->uvd.inst[i].ring_enc[0].wptr_offs] = 0; | 735 | adev->wb.wb[adev->uvd.inst[i].ring_enc[0].wptr_offs] = 0; |
700 | adev->uvd.inst[i].ring_enc[0].wptr = 0; | 736 | adev->uvd.inst[i].ring_enc[0].wptr = 0; |
@@ -751,6 +787,8 @@ static int uvd_v7_0_sriov_start(struct amdgpu_device *adev) | |||
751 | init_table += header->uvd_table_offset; | 787 | init_table += header->uvd_table_offset; |
752 | 788 | ||
753 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { | 789 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { |
790 | if (adev->uvd.harvest_config & (1 << i)) | ||
791 | continue; | ||
754 | ring = &adev->uvd.inst[i].ring; | 792 | ring = &adev->uvd.inst[i].ring; |
755 | ring->wptr = 0; | 793 | ring->wptr = 0; |
756 | size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4); | 794 | size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4); |
@@ -890,6 +928,8 @@ static int uvd_v7_0_start(struct amdgpu_device *adev) | |||
890 | int i, j, k, r; | 928 | int i, j, k, r; |
891 | 929 | ||
892 | for (k = 0; k < adev->uvd.num_uvd_inst; ++k) { | 930 | for (k = 0; k < adev->uvd.num_uvd_inst; ++k) { |
931 | if (adev->uvd.harvest_config & (1 << k)) | ||
932 | continue; | ||
893 | /* disable DPG */ | 933 | /* disable DPG */ |
894 | WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_POWER_STATUS), 0, | 934 | WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_POWER_STATUS), 0, |
895 | ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); | 935 | ~UVD_POWER_STATUS__UVD_PG_MODE_MASK); |
@@ -902,6 +942,8 @@ static int uvd_v7_0_start(struct amdgpu_device *adev) | |||
902 | uvd_v7_0_mc_resume(adev); | 942 | uvd_v7_0_mc_resume(adev); |
903 | 943 | ||
904 | for (k = 0; k < adev->uvd.num_uvd_inst; ++k) { | 944 | for (k = 0; k < adev->uvd.num_uvd_inst; ++k) { |
945 | if (adev->uvd.harvest_config & (1 << k)) | ||
946 | continue; | ||
905 | ring = &adev->uvd.inst[k].ring; | 947 | ring = &adev->uvd.inst[k].ring; |
906 | /* disable clock gating */ | 948 | /* disable clock gating */ |
907 | WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_CGC_CTRL), 0, | 949 | WREG32_P(SOC15_REG_OFFSET(UVD, k, mmUVD_CGC_CTRL), 0, |
@@ -1069,6 +1111,8 @@ static void uvd_v7_0_stop(struct amdgpu_device *adev) | |||
1069 | uint8_t i = 0; | 1111 | uint8_t i = 0; |
1070 | 1112 | ||
1071 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { | 1113 | for (i = 0; i < adev->uvd.num_uvd_inst; ++i) { |
1114 | if (adev->uvd.harvest_config & (1 << i)) | ||
1115 | continue; | ||
1072 | /* force RBC into idle state */ | 1116 | /* force RBC into idle state */ |
1073 | WREG32_SOC15(UVD, i, mmUVD_RBC_RB_CNTL, 0x11010101); | 1117 | WREG32_SOC15(UVD, i, mmUVD_RBC_RB_CNTL, 0x11010101); |
1074 | 1118 | ||
@@ -1785,6 +1829,8 @@ static void uvd_v7_0_set_ring_funcs(struct amdgpu_device *adev) | |||
1785 | int i; | 1829 | int i; |
1786 | 1830 | ||
1787 | for (i = 0; i < adev->uvd.num_uvd_inst; i++) { | 1831 | for (i = 0; i < adev->uvd.num_uvd_inst; i++) { |
1832 | if (adev->uvd.harvest_config & (1 << i)) | ||
1833 | continue; | ||
1788 | adev->uvd.inst[i].ring.funcs = &uvd_v7_0_ring_vm_funcs; | 1834 | adev->uvd.inst[i].ring.funcs = &uvd_v7_0_ring_vm_funcs; |
1789 | adev->uvd.inst[i].ring.me = i; | 1835 | adev->uvd.inst[i].ring.me = i; |
1790 | DRM_INFO("UVD(%d) is enabled in VM mode\n", i); | 1836 | DRM_INFO("UVD(%d) is enabled in VM mode\n", i); |
@@ -1796,6 +1842,8 @@ static void uvd_v7_0_set_enc_ring_funcs(struct amdgpu_device *adev) | |||
1796 | int i, j; | 1842 | int i, j; |
1797 | 1843 | ||
1798 | for (j = 0; j < adev->uvd.num_uvd_inst; j++) { | 1844 | for (j = 0; j < adev->uvd.num_uvd_inst; j++) { |
1845 | if (adev->uvd.harvest_config & (1 << j)) | ||
1846 | continue; | ||
1799 | for (i = 0; i < adev->uvd.num_enc_rings; ++i) { | 1847 | for (i = 0; i < adev->uvd.num_enc_rings; ++i) { |
1800 | adev->uvd.inst[j].ring_enc[i].funcs = &uvd_v7_0_enc_ring_vm_funcs; | 1848 | adev->uvd.inst[j].ring_enc[i].funcs = &uvd_v7_0_enc_ring_vm_funcs; |
1801 | adev->uvd.inst[j].ring_enc[i].me = j; | 1849 | adev->uvd.inst[j].ring_enc[i].me = j; |
@@ -1815,6 +1863,8 @@ static void uvd_v7_0_set_irq_funcs(struct amdgpu_device *adev) | |||
1815 | int i; | 1863 | int i; |
1816 | 1864 | ||
1817 | for (i = 0; i < adev->uvd.num_uvd_inst; i++) { | 1865 | for (i = 0; i < adev->uvd.num_uvd_inst; i++) { |
1866 | if (adev->uvd.harvest_config & (1 << i)) | ||
1867 | continue; | ||
1818 | adev->uvd.inst[i].irq.num_types = adev->uvd.num_enc_rings + 1; | 1868 | adev->uvd.inst[i].irq.num_types = adev->uvd.num_enc_rings + 1; |
1819 | adev->uvd.inst[i].irq.funcs = &uvd_v7_0_irq_funcs; | 1869 | adev->uvd.inst[i].irq.funcs = &uvd_v7_0_irq_funcs; |
1820 | } | 1870 | } |