diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 137 |
1 files changed, 57 insertions, 80 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index b2eae86bf906..627542b22ae4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #define FIRMWARE_POLARIS12 "amdgpu/polaris12_uvd.bin" | 68 | #define FIRMWARE_POLARIS12 "amdgpu/polaris12_uvd.bin" |
69 | 69 | ||
70 | #define FIRMWARE_VEGA10 "amdgpu/vega10_uvd.bin" | 70 | #define FIRMWARE_VEGA10 "amdgpu/vega10_uvd.bin" |
71 | #define FIRMWARE_VEGA12 "amdgpu/vega12_uvd.bin" | ||
71 | 72 | ||
72 | #define mmUVD_GPCOM_VCPU_DATA0_VEGA10 (0x03c4 + 0x7e00) | 73 | #define mmUVD_GPCOM_VCPU_DATA0_VEGA10 (0x03c4 + 0x7e00) |
73 | #define mmUVD_GPCOM_VCPU_DATA1_VEGA10 (0x03c5 + 0x7e00) | 74 | #define mmUVD_GPCOM_VCPU_DATA1_VEGA10 (0x03c5 + 0x7e00) |
@@ -110,6 +111,7 @@ MODULE_FIRMWARE(FIRMWARE_POLARIS11); | |||
110 | MODULE_FIRMWARE(FIRMWARE_POLARIS12); | 111 | MODULE_FIRMWARE(FIRMWARE_POLARIS12); |
111 | 112 | ||
112 | MODULE_FIRMWARE(FIRMWARE_VEGA10); | 113 | MODULE_FIRMWARE(FIRMWARE_VEGA10); |
114 | MODULE_FIRMWARE(FIRMWARE_VEGA12); | ||
113 | 115 | ||
114 | static void amdgpu_uvd_idle_work_handler(struct work_struct *work); | 116 | static void amdgpu_uvd_idle_work_handler(struct work_struct *work); |
115 | 117 | ||
@@ -161,11 +163,14 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) | |||
161 | case CHIP_POLARIS11: | 163 | case CHIP_POLARIS11: |
162 | fw_name = FIRMWARE_POLARIS11; | 164 | fw_name = FIRMWARE_POLARIS11; |
163 | break; | 165 | break; |
166 | case CHIP_POLARIS12: | ||
167 | fw_name = FIRMWARE_POLARIS12; | ||
168 | break; | ||
164 | case CHIP_VEGA10: | 169 | case CHIP_VEGA10: |
165 | fw_name = FIRMWARE_VEGA10; | 170 | fw_name = FIRMWARE_VEGA10; |
166 | break; | 171 | break; |
167 | case CHIP_POLARIS12: | 172 | case CHIP_VEGA12: |
168 | fw_name = FIRMWARE_POLARIS12; | 173 | fw_name = FIRMWARE_VEGA12; |
169 | break; | 174 | break; |
170 | default: | 175 | default: |
171 | return -EINVAL; | 176 | return -EINVAL; |
@@ -299,12 +304,15 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev) | |||
299 | 304 | ||
300 | cancel_delayed_work_sync(&adev->uvd.idle_work); | 305 | cancel_delayed_work_sync(&adev->uvd.idle_work); |
301 | 306 | ||
302 | for (i = 0; i < adev->uvd.max_handles; ++i) | 307 | /* only valid for physical mode */ |
303 | if (atomic_read(&adev->uvd.handles[i])) | 308 | if (adev->asic_type < CHIP_POLARIS10) { |
304 | break; | 309 | for (i = 0; i < adev->uvd.max_handles; ++i) |
310 | if (atomic_read(&adev->uvd.handles[i])) | ||
311 | break; | ||
305 | 312 | ||
306 | if (i == AMDGPU_MAX_UVD_HANDLES) | 313 | if (i == adev->uvd.max_handles) |
307 | return 0; | 314 | return 0; |
315 | } | ||
308 | 316 | ||
309 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); | 317 | size = amdgpu_bo_size(adev->uvd.vcpu_bo); |
310 | ptr = adev->uvd.cpu_addr; | 318 | ptr = adev->uvd.cpu_addr; |
@@ -952,37 +960,28 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) | |||
952 | static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, | 960 | static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, |
953 | bool direct, struct dma_fence **fence) | 961 | bool direct, struct dma_fence **fence) |
954 | { | 962 | { |
955 | struct ttm_operation_ctx ctx = { true, false }; | 963 | struct amdgpu_device *adev = ring->adev; |
956 | struct ttm_validate_buffer tv; | 964 | struct dma_fence *f = NULL; |
957 | struct ww_acquire_ctx ticket; | ||
958 | struct list_head head; | ||
959 | struct amdgpu_job *job; | 965 | struct amdgpu_job *job; |
960 | struct amdgpu_ib *ib; | 966 | struct amdgpu_ib *ib; |
961 | struct dma_fence *f = NULL; | ||
962 | struct amdgpu_device *adev = ring->adev; | ||
963 | uint64_t addr; | ||
964 | uint32_t data[4]; | 967 | uint32_t data[4]; |
965 | int i, r; | 968 | uint64_t addr; |
966 | 969 | long r; | |
967 | memset(&tv, 0, sizeof(tv)); | 970 | int i; |
968 | tv.bo = &bo->tbo; | ||
969 | |||
970 | INIT_LIST_HEAD(&head); | ||
971 | list_add(&tv.head, &head); | ||
972 | 971 | ||
973 | r = ttm_eu_reserve_buffers(&ticket, &head, true, NULL); | 972 | amdgpu_bo_kunmap(bo); |
974 | if (r) | 973 | amdgpu_bo_unpin(bo); |
975 | return r; | ||
976 | 974 | ||
977 | if (!ring->adev->uvd.address_64_bit) { | 975 | if (!ring->adev->uvd.address_64_bit) { |
976 | struct ttm_operation_ctx ctx = { true, false }; | ||
977 | |||
978 | amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); | 978 | amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM); |
979 | amdgpu_uvd_force_into_uvd_segment(bo); | 979 | amdgpu_uvd_force_into_uvd_segment(bo); |
980 | r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); | ||
981 | if (r) | ||
982 | goto err; | ||
980 | } | 983 | } |
981 | 984 | ||
982 | r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); | ||
983 | if (r) | ||
984 | goto err; | ||
985 | |||
986 | r = amdgpu_job_alloc_with_ib(adev, 64, &job); | 985 | r = amdgpu_job_alloc_with_ib(adev, 64, &job); |
987 | if (r) | 986 | if (r) |
988 | goto err; | 987 | goto err; |
@@ -1014,6 +1013,14 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, | |||
1014 | ib->length_dw = 16; | 1013 | ib->length_dw = 16; |
1015 | 1014 | ||
1016 | if (direct) { | 1015 | if (direct) { |
1016 | r = reservation_object_wait_timeout_rcu(bo->tbo.resv, | ||
1017 | true, false, | ||
1018 | msecs_to_jiffies(10)); | ||
1019 | if (r == 0) | ||
1020 | r = -ETIMEDOUT; | ||
1021 | if (r < 0) | ||
1022 | goto err_free; | ||
1023 | |||
1017 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); | 1024 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); |
1018 | job->fence = dma_fence_get(f); | 1025 | job->fence = dma_fence_get(f); |
1019 | if (r) | 1026 | if (r) |
@@ -1021,17 +1028,23 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, | |||
1021 | 1028 | ||
1022 | amdgpu_job_free(job); | 1029 | amdgpu_job_free(job); |
1023 | } else { | 1030 | } else { |
1031 | r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.resv, | ||
1032 | AMDGPU_FENCE_OWNER_UNDEFINED, false); | ||
1033 | if (r) | ||
1034 | goto err_free; | ||
1035 | |||
1024 | r = amdgpu_job_submit(job, ring, &adev->uvd.entity, | 1036 | r = amdgpu_job_submit(job, ring, &adev->uvd.entity, |
1025 | AMDGPU_FENCE_OWNER_UNDEFINED, &f); | 1037 | AMDGPU_FENCE_OWNER_UNDEFINED, &f); |
1026 | if (r) | 1038 | if (r) |
1027 | goto err_free; | 1039 | goto err_free; |
1028 | } | 1040 | } |
1029 | 1041 | ||
1030 | ttm_eu_fence_buffer_objects(&ticket, &head, f); | 1042 | amdgpu_bo_fence(bo, f, false); |
1043 | amdgpu_bo_unreserve(bo); | ||
1044 | amdgpu_bo_unref(&bo); | ||
1031 | 1045 | ||
1032 | if (fence) | 1046 | if (fence) |
1033 | *fence = dma_fence_get(f); | 1047 | *fence = dma_fence_get(f); |
1034 | amdgpu_bo_unref(&bo); | ||
1035 | dma_fence_put(f); | 1048 | dma_fence_put(f); |
1036 | 1049 | ||
1037 | return 0; | 1050 | return 0; |
@@ -1040,7 +1053,8 @@ err_free: | |||
1040 | amdgpu_job_free(job); | 1053 | amdgpu_job_free(job); |
1041 | 1054 | ||
1042 | err: | 1055 | err: |
1043 | ttm_eu_backoff_reservation(&ticket, &head); | 1056 | amdgpu_bo_unreserve(bo); |
1057 | amdgpu_bo_unref(&bo); | ||
1044 | return r; | 1058 | return r; |
1045 | } | 1059 | } |
1046 | 1060 | ||
@@ -1051,31 +1065,16 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
1051 | struct dma_fence **fence) | 1065 | struct dma_fence **fence) |
1052 | { | 1066 | { |
1053 | struct amdgpu_device *adev = ring->adev; | 1067 | struct amdgpu_device *adev = ring->adev; |
1054 | struct amdgpu_bo *bo; | 1068 | struct amdgpu_bo *bo = NULL; |
1055 | uint32_t *msg; | 1069 | uint32_t *msg; |
1056 | int r, i; | 1070 | int r, i; |
1057 | 1071 | ||
1058 | r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true, | 1072 | r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE, |
1059 | AMDGPU_GEM_DOMAIN_VRAM, | 1073 | AMDGPU_GEM_DOMAIN_VRAM, |
1060 | AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | | 1074 | &bo, NULL, (void **)&msg); |
1061 | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, | ||
1062 | NULL, NULL, 0, &bo); | ||
1063 | if (r) | 1075 | if (r) |
1064 | return r; | 1076 | return r; |
1065 | 1077 | ||
1066 | r = amdgpu_bo_reserve(bo, false); | ||
1067 | if (r) { | ||
1068 | amdgpu_bo_unref(&bo); | ||
1069 | return r; | ||
1070 | } | ||
1071 | |||
1072 | r = amdgpu_bo_kmap(bo, (void **)&msg); | ||
1073 | if (r) { | ||
1074 | amdgpu_bo_unreserve(bo); | ||
1075 | amdgpu_bo_unref(&bo); | ||
1076 | return r; | ||
1077 | } | ||
1078 | |||
1079 | /* stitch together an UVD create msg */ | 1078 | /* stitch together an UVD create msg */ |
1080 | msg[0] = cpu_to_le32(0x00000de4); | 1079 | msg[0] = cpu_to_le32(0x00000de4); |
1081 | msg[1] = cpu_to_le32(0x00000000); | 1080 | msg[1] = cpu_to_le32(0x00000000); |
@@ -1091,9 +1090,6 @@ int amdgpu_uvd_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
1091 | for (i = 11; i < 1024; ++i) | 1090 | for (i = 11; i < 1024; ++i) |
1092 | msg[i] = cpu_to_le32(0x0); | 1091 | msg[i] = cpu_to_le32(0x0); |
1093 | 1092 | ||
1094 | amdgpu_bo_kunmap(bo); | ||
1095 | amdgpu_bo_unreserve(bo); | ||
1096 | |||
1097 | return amdgpu_uvd_send_msg(ring, bo, true, fence); | 1093 | return amdgpu_uvd_send_msg(ring, bo, true, fence); |
1098 | } | 1094 | } |
1099 | 1095 | ||
@@ -1101,31 +1097,16 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
1101 | bool direct, struct dma_fence **fence) | 1097 | bool direct, struct dma_fence **fence) |
1102 | { | 1098 | { |
1103 | struct amdgpu_device *adev = ring->adev; | 1099 | struct amdgpu_device *adev = ring->adev; |
1104 | struct amdgpu_bo *bo; | 1100 | struct amdgpu_bo *bo = NULL; |
1105 | uint32_t *msg; | 1101 | uint32_t *msg; |
1106 | int r, i; | 1102 | int r, i; |
1107 | 1103 | ||
1108 | r = amdgpu_bo_create(adev, 1024, PAGE_SIZE, true, | 1104 | r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE, |
1109 | AMDGPU_GEM_DOMAIN_VRAM, | 1105 | AMDGPU_GEM_DOMAIN_VRAM, |
1110 | AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | | 1106 | &bo, NULL, (void **)&msg); |
1111 | AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, | ||
1112 | NULL, NULL, 0, &bo); | ||
1113 | if (r) | 1107 | if (r) |
1114 | return r; | 1108 | return r; |
1115 | 1109 | ||
1116 | r = amdgpu_bo_reserve(bo, false); | ||
1117 | if (r) { | ||
1118 | amdgpu_bo_unref(&bo); | ||
1119 | return r; | ||
1120 | } | ||
1121 | |||
1122 | r = amdgpu_bo_kmap(bo, (void **)&msg); | ||
1123 | if (r) { | ||
1124 | amdgpu_bo_unreserve(bo); | ||
1125 | amdgpu_bo_unref(&bo); | ||
1126 | return r; | ||
1127 | } | ||
1128 | |||
1129 | /* stitch together an UVD destroy msg */ | 1110 | /* stitch together an UVD destroy msg */ |
1130 | msg[0] = cpu_to_le32(0x00000de4); | 1111 | msg[0] = cpu_to_le32(0x00000de4); |
1131 | msg[1] = cpu_to_le32(0x00000002); | 1112 | msg[1] = cpu_to_le32(0x00000002); |
@@ -1134,9 +1115,6 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle, | |||
1134 | for (i = 4; i < 1024; ++i) | 1115 | for (i = 4; i < 1024; ++i) |
1135 | msg[i] = cpu_to_le32(0x0); | 1116 | msg[i] = cpu_to_le32(0x0); |
1136 | 1117 | ||
1137 | amdgpu_bo_kunmap(bo); | ||
1138 | amdgpu_bo_unreserve(bo); | ||
1139 | |||
1140 | return amdgpu_uvd_send_msg(ring, bo, direct, fence); | 1118 | return amdgpu_uvd_send_msg(ring, bo, direct, fence); |
1141 | } | 1119 | } |
1142 | 1120 | ||
@@ -1146,9 +1124,6 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work) | |||
1146 | container_of(work, struct amdgpu_device, uvd.idle_work.work); | 1124 | container_of(work, struct amdgpu_device, uvd.idle_work.work); |
1147 | unsigned fences = amdgpu_fence_count_emitted(&adev->uvd.ring); | 1125 | unsigned fences = amdgpu_fence_count_emitted(&adev->uvd.ring); |
1148 | 1126 | ||
1149 | if (amdgpu_sriov_vf(adev)) | ||
1150 | return; | ||
1151 | |||
1152 | if (fences == 0) { | 1127 | if (fences == 0) { |
1153 | if (adev->pm.dpm_enabled) { | 1128 | if (adev->pm.dpm_enabled) { |
1154 | amdgpu_dpm_enable_uvd(adev, false); | 1129 | amdgpu_dpm_enable_uvd(adev, false); |
@@ -1168,11 +1143,12 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work) | |||
1168 | void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring) | 1143 | void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring) |
1169 | { | 1144 | { |
1170 | struct amdgpu_device *adev = ring->adev; | 1145 | struct amdgpu_device *adev = ring->adev; |
1171 | bool set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work); | 1146 | bool set_clocks; |
1172 | 1147 | ||
1173 | if (amdgpu_sriov_vf(adev)) | 1148 | if (amdgpu_sriov_vf(adev)) |
1174 | return; | 1149 | return; |
1175 | 1150 | ||
1151 | set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work); | ||
1176 | if (set_clocks) { | 1152 | if (set_clocks) { |
1177 | if (adev->pm.dpm_enabled) { | 1153 | if (adev->pm.dpm_enabled) { |
1178 | amdgpu_dpm_enable_uvd(adev, true); | 1154 | amdgpu_dpm_enable_uvd(adev, true); |
@@ -1188,7 +1164,8 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring) | |||
1188 | 1164 | ||
1189 | void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring) | 1165 | void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring) |
1190 | { | 1166 | { |
1191 | schedule_delayed_work(&ring->adev->uvd.idle_work, UVD_IDLE_TIMEOUT); | 1167 | if (!amdgpu_sriov_vf(ring->adev)) |
1168 | schedule_delayed_work(&ring->adev->uvd.idle_work, UVD_IDLE_TIMEOUT); | ||
1192 | } | 1169 | } |
1193 | 1170 | ||
1194 | /** | 1171 | /** |