diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index d9c88d13f8db..b11f4e8868d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | |||
@@ -40,9 +40,16 @@ | |||
40 | #include "uvd/uvd_4_2_d.h" | 40 | #include "uvd/uvd_4_2_d.h" |
41 | 41 | ||
42 | /* 1 second timeout */ | 42 | /* 1 second timeout */ |
43 | #define UVD_IDLE_TIMEOUT_MS 1000 | 43 | #define UVD_IDLE_TIMEOUT msecs_to_jiffies(1000) |
44 | |||
45 | /* Firmware versions for VI */ | ||
46 | #define FW_1_65_10 ((1 << 24) | (65 << 16) | (10 << 8)) | ||
47 | #define FW_1_87_11 ((1 << 24) | (87 << 16) | (11 << 8)) | ||
48 | #define FW_1_87_12 ((1 << 24) | (87 << 16) | (12 << 8)) | ||
49 | #define FW_1_37_15 ((1 << 24) | (37 << 16) | (15 << 8)) | ||
50 | |||
44 | /* Polaris10/11 firmware version */ | 51 | /* Polaris10/11 firmware version */ |
45 | #define FW_1_66_16 ((1 << 24) | (66 << 16) | (16 << 8)) | 52 | #define FW_1_66_16 ((1 << 24) | (66 << 16) | (16 << 8)) |
46 | 53 | ||
47 | /* Firmware Names */ | 54 | /* Firmware Names */ |
48 | #ifdef CONFIG_DRM_AMDGPU_CIK | 55 | #ifdef CONFIG_DRM_AMDGPU_CIK |
@@ -92,7 +99,6 @@ MODULE_FIRMWARE(FIRMWARE_STONEY); | |||
92 | MODULE_FIRMWARE(FIRMWARE_POLARIS10); | 99 | MODULE_FIRMWARE(FIRMWARE_POLARIS10); |
93 | MODULE_FIRMWARE(FIRMWARE_POLARIS11); | 100 | MODULE_FIRMWARE(FIRMWARE_POLARIS11); |
94 | 101 | ||
95 | static void amdgpu_uvd_note_usage(struct amdgpu_device *adev); | ||
96 | static void amdgpu_uvd_idle_work_handler(struct work_struct *work); | 102 | static void amdgpu_uvd_idle_work_handler(struct work_struct *work); |
97 | 103 | ||
98 | int amdgpu_uvd_sw_init(struct amdgpu_device *adev) | 104 | int amdgpu_uvd_sw_init(struct amdgpu_device *adev) |
@@ -246,6 +252,23 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev) | |||
246 | if (!amdgpu_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0)) | 252 | if (!amdgpu_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0)) |
247 | adev->uvd.address_64_bit = true; | 253 | adev->uvd.address_64_bit = true; |
248 | 254 | ||
255 | switch (adev->asic_type) { | ||
256 | case CHIP_TONGA: | ||
257 | adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_65_10; | ||
258 | break; | ||
259 | case CHIP_CARRIZO: | ||
260 | adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_87_11; | ||
261 | break; | ||
262 | case CHIP_FIJI: | ||
263 | adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_87_12; | ||
264 | break; | ||
265 | case CHIP_STONEY: | ||
266 | adev->uvd.use_ctx_buf = adev->uvd.fw_version >= FW_1_37_15; | ||
267 | break; | ||
268 | default: | ||
269 | adev->uvd.use_ctx_buf = adev->asic_type >= CHIP_POLARIS10; | ||
270 | } | ||
271 | |||
249 | return 0; | 272 | return 0; |
250 | } | 273 | } |
251 | 274 | ||
@@ -346,8 +369,6 @@ void amdgpu_uvd_free_handles(struct amdgpu_device *adev, struct drm_file *filp) | |||
346 | if (handle != 0 && adev->uvd.filp[i] == filp) { | 369 | if (handle != 0 && adev->uvd.filp[i] == filp) { |
347 | struct fence *fence; | 370 | struct fence *fence; |
348 | 371 | ||
349 | amdgpu_uvd_note_usage(adev); | ||
350 | |||
351 | r = amdgpu_uvd_get_destroy_msg(ring, handle, | 372 | r = amdgpu_uvd_get_destroy_msg(ring, handle, |
352 | false, &fence); | 373 | false, &fence); |
353 | if (r) { | 374 | if (r) { |
@@ -438,7 +459,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg, | |||
438 | unsigned fs_in_mb = width_in_mb * height_in_mb; | 459 | unsigned fs_in_mb = width_in_mb * height_in_mb; |
439 | 460 | ||
440 | unsigned image_size, tmp, min_dpb_size, num_dpb_buffer; | 461 | unsigned image_size, tmp, min_dpb_size, num_dpb_buffer; |
441 | unsigned min_ctx_size = 0; | 462 | unsigned min_ctx_size = ~0; |
442 | 463 | ||
443 | image_size = width * height; | 464 | image_size = width * height; |
444 | image_size += image_size / 2; | 465 | image_size += image_size / 2; |
@@ -557,7 +578,7 @@ static int amdgpu_uvd_cs_msg_decode(struct amdgpu_device *adev, uint32_t *msg, | |||
557 | /* reference picture buffer */ | 578 | /* reference picture buffer */ |
558 | min_dpb_size = image_size * num_dpb_buffer; | 579 | min_dpb_size = image_size * num_dpb_buffer; |
559 | 580 | ||
560 | if (adev->asic_type < CHIP_POLARIS10){ | 581 | if (!adev->uvd.use_ctx_buf){ |
561 | /* macroblock context buffer */ | 582 | /* macroblock context buffer */ |
562 | min_dpb_size += | 583 | min_dpb_size += |
563 | width_in_mb * height_in_mb * num_dpb_buffer * 192; | 584 | width_in_mb * height_in_mb * num_dpb_buffer * 192; |
@@ -662,7 +683,7 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx, | |||
662 | } | 683 | } |
663 | 684 | ||
664 | DRM_ERROR("No more free UVD handles!\n"); | 685 | DRM_ERROR("No more free UVD handles!\n"); |
665 | return -EINVAL; | 686 | return -ENOSPC; |
666 | 687 | ||
667 | case 1: | 688 | case 1: |
668 | /* it's a decode msg, calc buffer sizes */ | 689 | /* it's a decode msg, calc buffer sizes */ |
@@ -913,8 +934,6 @@ int amdgpu_uvd_ring_parse_cs(struct amdgpu_cs_parser *parser, uint32_t ib_idx) | |||
913 | return -EINVAL; | 934 | return -EINVAL; |
914 | } | 935 | } |
915 | 936 | ||
916 | amdgpu_uvd_note_usage(ctx.parser->adev); | ||
917 | |||
918 | return 0; | 937 | return 0; |
919 | } | 938 | } |
920 | 939 | ||
@@ -968,7 +987,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, | |||
968 | 987 | ||
969 | if (direct) { | 988 | if (direct) { |
970 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); | 989 | r = amdgpu_ib_schedule(ring, 1, ib, NULL, NULL, &f); |
971 | job->fence = f; | 990 | job->fence = fence_get(f); |
972 | if (r) | 991 | if (r) |
973 | goto err_free; | 992 | goto err_free; |
974 | 993 | ||
@@ -1106,24 +1125,18 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work) | |||
1106 | if (fences == 0 && handles == 0) { | 1125 | if (fences == 0 && handles == 0) { |
1107 | if (adev->pm.dpm_enabled) { | 1126 | if (adev->pm.dpm_enabled) { |
1108 | amdgpu_dpm_enable_uvd(adev, false); | 1127 | amdgpu_dpm_enable_uvd(adev, false); |
1109 | /* just work around for uvd clock remain high even | ||
1110 | * when uvd dpm disabled on Polaris10 */ | ||
1111 | if (adev->asic_type == CHIP_POLARIS10) | ||
1112 | amdgpu_asic_set_uvd_clocks(adev, 0, 0); | ||
1113 | } else { | 1128 | } else { |
1114 | amdgpu_asic_set_uvd_clocks(adev, 0, 0); | 1129 | amdgpu_asic_set_uvd_clocks(adev, 0, 0); |
1115 | } | 1130 | } |
1116 | } else { | 1131 | } else { |
1117 | schedule_delayed_work(&adev->uvd.idle_work, | 1132 | schedule_delayed_work(&adev->uvd.idle_work, UVD_IDLE_TIMEOUT); |
1118 | msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); | ||
1119 | } | 1133 | } |
1120 | } | 1134 | } |
1121 | 1135 | ||
1122 | static void amdgpu_uvd_note_usage(struct amdgpu_device *adev) | 1136 | void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring) |
1123 | { | 1137 | { |
1138 | struct amdgpu_device *adev = ring->adev; | ||
1124 | bool set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work); | 1139 | bool set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work); |
1125 | set_clocks &= schedule_delayed_work(&adev->uvd.idle_work, | ||
1126 | msecs_to_jiffies(UVD_IDLE_TIMEOUT_MS)); | ||
1127 | 1140 | ||
1128 | if (set_clocks) { | 1141 | if (set_clocks) { |
1129 | if (adev->pm.dpm_enabled) { | 1142 | if (adev->pm.dpm_enabled) { |
@@ -1133,3 +1146,48 @@ static void amdgpu_uvd_note_usage(struct amdgpu_device *adev) | |||
1133 | } | 1146 | } |
1134 | } | 1147 | } |
1135 | } | 1148 | } |
1149 | |||
1150 | void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring) | ||
1151 | { | ||
1152 | schedule_delayed_work(&ring->adev->uvd.idle_work, UVD_IDLE_TIMEOUT); | ||
1153 | } | ||
1154 | |||
1155 | /** | ||
1156 | * amdgpu_uvd_ring_test_ib - test ib execution | ||
1157 | * | ||
1158 | * @ring: amdgpu_ring pointer | ||
1159 | * | ||
1160 | * Test if we can successfully execute an IB | ||
1161 | */ | ||
1162 | int amdgpu_uvd_ring_test_ib(struct amdgpu_ring *ring, long timeout) | ||
1163 | { | ||
1164 | struct fence *fence; | ||
1165 | long r; | ||
1166 | |||
1167 | r = amdgpu_uvd_get_create_msg(ring, 1, NULL); | ||
1168 | if (r) { | ||
1169 | DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r); | ||
1170 | goto error; | ||
1171 | } | ||
1172 | |||
1173 | r = amdgpu_uvd_get_destroy_msg(ring, 1, true, &fence); | ||
1174 | if (r) { | ||
1175 | DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r); | ||
1176 | goto error; | ||
1177 | } | ||
1178 | |||
1179 | r = fence_wait_timeout(fence, false, timeout); | ||
1180 | if (r == 0) { | ||
1181 | DRM_ERROR("amdgpu: IB test timed out.\n"); | ||
1182 | r = -ETIMEDOUT; | ||
1183 | } else if (r < 0) { | ||
1184 | DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); | ||
1185 | } else { | ||
1186 | DRM_INFO("ib test on ring %d succeeded\n", ring->idx); | ||
1187 | r = 0; | ||
1188 | } | ||
1189 | |||
1190 | error: | ||
1191 | fence_put(fence); | ||
1192 | return r; | ||
1193 | } | ||