1280 lines · c
1/*2 * Copyright 2016 Advanced Micro Devices, Inc.3 * All Rights Reserved.4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the7 * "Software"), to deal in the Software without restriction, including8 * without limitation the rights to use, copy, modify, merge, publish,9 * distribute, sub license, and/or sell copies of the Software, and to10 * permit persons to whom the Software is furnished to do so, subject to11 * the following conditions:12 *13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL16 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,17 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE19 * USE OR OTHER DEALINGS IN THE SOFTWARE.20 *21 * The above copyright notice and this permission notice (including the22 * next paragraph) shall be included in all copies or substantial portions23 * of the Software.24 *25 */26 27#include <linux/firmware.h>28#include <linux/module.h>29#include <linux/dmi.h>30#include <linux/pci.h>31#include <linux/debugfs.h>32#include <drm/drm_drv.h>33 34#include "amdgpu.h"35#include "amdgpu_pm.h"36#include "amdgpu_vcn.h"37#include "soc15d.h"38 39/* Firmware Names */40#define FIRMWARE_RAVEN "amdgpu/raven_vcn.bin"41#define FIRMWARE_PICASSO "amdgpu/picasso_vcn.bin"42#define FIRMWARE_RAVEN2 "amdgpu/raven2_vcn.bin"43#define FIRMWARE_ARCTURUS "amdgpu/arcturus_vcn.bin"44#define FIRMWARE_RENOIR "amdgpu/renoir_vcn.bin"45#define FIRMWARE_GREEN_SARDINE "amdgpu/green_sardine_vcn.bin"46#define FIRMWARE_NAVI10 "amdgpu/navi10_vcn.bin"47#define FIRMWARE_NAVI14 "amdgpu/navi14_vcn.bin"48#define FIRMWARE_NAVI12 "amdgpu/navi12_vcn.bin"49#define FIRMWARE_SIENNA_CICHLID "amdgpu/sienna_cichlid_vcn.bin"50#define FIRMWARE_NAVY_FLOUNDER "amdgpu/navy_flounder_vcn.bin"51#define FIRMWARE_VANGOGH "amdgpu/vangogh_vcn.bin"52#define FIRMWARE_DIMGREY_CAVEFISH "amdgpu/dimgrey_cavefish_vcn.bin"53#define FIRMWARE_ALDEBARAN "amdgpu/aldebaran_vcn.bin"54#define FIRMWARE_BEIGE_GOBY "amdgpu/beige_goby_vcn.bin"55#define FIRMWARE_YELLOW_CARP "amdgpu/yellow_carp_vcn.bin"56#define FIRMWARE_VCN_3_1_2 "amdgpu/vcn_3_1_2.bin"57#define FIRMWARE_VCN4_0_0 "amdgpu/vcn_4_0_0.bin"58#define FIRMWARE_VCN4_0_2 "amdgpu/vcn_4_0_2.bin"59#define FIRMWARE_VCN4_0_3 "amdgpu/vcn_4_0_3.bin"60#define FIRMWARE_VCN4_0_4 "amdgpu/vcn_4_0_4.bin"61#define FIRMWARE_VCN4_0_5 "amdgpu/vcn_4_0_5.bin"62#define FIRMWARE_VCN4_0_6 "amdgpu/vcn_4_0_6.bin"63#define FIRMWARE_VCN4_0_6_1 "amdgpu/vcn_4_0_6_1.bin"64#define FIRMWARE_VCN5_0_0 "amdgpu/vcn_5_0_0.bin"65 66MODULE_FIRMWARE(FIRMWARE_RAVEN);67MODULE_FIRMWARE(FIRMWARE_PICASSO);68MODULE_FIRMWARE(FIRMWARE_RAVEN2);69MODULE_FIRMWARE(FIRMWARE_ARCTURUS);70MODULE_FIRMWARE(FIRMWARE_RENOIR);71MODULE_FIRMWARE(FIRMWARE_GREEN_SARDINE);72MODULE_FIRMWARE(FIRMWARE_ALDEBARAN);73MODULE_FIRMWARE(FIRMWARE_NAVI10);74MODULE_FIRMWARE(FIRMWARE_NAVI14);75MODULE_FIRMWARE(FIRMWARE_NAVI12);76MODULE_FIRMWARE(FIRMWARE_SIENNA_CICHLID);77MODULE_FIRMWARE(FIRMWARE_NAVY_FLOUNDER);78MODULE_FIRMWARE(FIRMWARE_VANGOGH);79MODULE_FIRMWARE(FIRMWARE_DIMGREY_CAVEFISH);80MODULE_FIRMWARE(FIRMWARE_BEIGE_GOBY);81MODULE_FIRMWARE(FIRMWARE_YELLOW_CARP);82MODULE_FIRMWARE(FIRMWARE_VCN_3_1_2);83MODULE_FIRMWARE(FIRMWARE_VCN4_0_0);84MODULE_FIRMWARE(FIRMWARE_VCN4_0_2);85MODULE_FIRMWARE(FIRMWARE_VCN4_0_3);86MODULE_FIRMWARE(FIRMWARE_VCN4_0_4);87MODULE_FIRMWARE(FIRMWARE_VCN4_0_5);88MODULE_FIRMWARE(FIRMWARE_VCN4_0_6);89MODULE_FIRMWARE(FIRMWARE_VCN4_0_6_1);90MODULE_FIRMWARE(FIRMWARE_VCN5_0_0);91 92static void amdgpu_vcn_idle_work_handler(struct work_struct *work);93 94int amdgpu_vcn_early_init(struct amdgpu_device *adev)95{96 char ucode_prefix[25];97 int r, i;98 99 amdgpu_ucode_ip_version_decode(adev, UVD_HWIP, ucode_prefix, sizeof(ucode_prefix));100 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {101 if (i == 1 && amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(4, 0, 6))102 r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], "amdgpu/%s_%d.bin", ucode_prefix, i);103 else104 r = amdgpu_ucode_request(adev, &adev->vcn.fw[i], "amdgpu/%s.bin", ucode_prefix);105 if (r) {106 amdgpu_ucode_release(&adev->vcn.fw[i]);107 return r;108 }109 }110 return r;111}112 113int amdgpu_vcn_sw_init(struct amdgpu_device *adev)114{115 unsigned long bo_size;116 const struct common_firmware_header *hdr;117 unsigned char fw_check;118 unsigned int fw_shared_size, log_offset;119 int i, r;120 121 INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);122 mutex_init(&adev->vcn.vcn_pg_lock);123 mutex_init(&adev->vcn.vcn1_jpeg1_workaround);124 atomic_set(&adev->vcn.total_submission_cnt, 0);125 for (i = 0; i < adev->vcn.num_vcn_inst; i++)126 atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);127 128 if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&129 (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))130 adev->vcn.indirect_sram = true;131 132 /*133 * Some Steam Deck's BIOS versions are incompatible with the134 * indirect SRAM mode, leading to amdgpu being unable to get135 * properly probed (and even potentially crashing the kernel).136 * Hence, check for these versions here - notice this is137 * restricted to Vangogh (Deck's APU).138 */139 if (amdgpu_ip_version(adev, UVD_HWIP, 0) == IP_VERSION(3, 0, 2)) {140 const char *bios_ver = dmi_get_system_info(DMI_BIOS_VERSION);141 142 if (bios_ver && (!strncmp("F7A0113", bios_ver, 7) ||143 !strncmp("F7A0114", bios_ver, 7))) {144 adev->vcn.indirect_sram = false;145 dev_info(adev->dev,146 "Steam Deck quirk: indirect SRAM disabled on BIOS %s\n", bios_ver);147 }148 }149 150 /* from vcn4 and above, only unified queue is used */151 adev->vcn.using_unified_queue =152 amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0);153 154 hdr = (const struct common_firmware_header *)adev->vcn.fw[0]->data;155 adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);156 157 /* Bit 20-23, it is encode major and non-zero for new naming convention.158 * This field is part of version minor and DRM_DISABLED_FLAG in old naming159 * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG160 * is zero in old naming convention, this field is always zero so far.161 * These four bits are used to tell which naming convention is present.162 */163 fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;164 if (fw_check) {165 unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;166 167 fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;168 enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;169 enc_major = fw_check;170 dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;171 vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;172 DRM_INFO("Found VCN firmware Version ENC: %u.%u DEC: %u VEP: %u Revision: %u\n",173 enc_major, enc_minor, dec_ver, vep, fw_rev);174 } else {175 unsigned int version_major, version_minor, family_id;176 177 family_id = le32_to_cpu(hdr->ucode_version) & 0xff;178 version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;179 version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;180 DRM_INFO("Found VCN firmware Version: %u.%u Family ID: %u\n",181 version_major, version_minor, family_id);182 }183 184 bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;185 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)186 bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);187 188 if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(5, 0, 0)) {189 fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn5_fw_shared));190 log_offset = offsetof(struct amdgpu_vcn5_fw_shared, fw_log);191 } else if (amdgpu_ip_version(adev, UVD_HWIP, 0) >= IP_VERSION(4, 0, 0)) {192 fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared));193 log_offset = offsetof(struct amdgpu_vcn4_fw_shared, fw_log);194 } else {195 fw_shared_size = AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_fw_shared));196 log_offset = offsetof(struct amdgpu_fw_shared, fw_log);197 }198 199 bo_size += fw_shared_size;200 201 if (amdgpu_vcnfw_log)202 bo_size += AMDGPU_VCNFW_LOG_SIZE;203 204 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {205 if (adev->vcn.harvest_config & (1 << i))206 continue;207 208 r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,209 AMDGPU_GEM_DOMAIN_VRAM |210 AMDGPU_GEM_DOMAIN_GTT,211 &adev->vcn.inst[i].vcpu_bo,212 &adev->vcn.inst[i].gpu_addr,213 &adev->vcn.inst[i].cpu_addr);214 if (r) {215 dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);216 return r;217 }218 219 adev->vcn.inst[i].fw_shared.cpu_addr = adev->vcn.inst[i].cpu_addr +220 bo_size - fw_shared_size;221 adev->vcn.inst[i].fw_shared.gpu_addr = adev->vcn.inst[i].gpu_addr +222 bo_size - fw_shared_size;223 224 adev->vcn.inst[i].fw_shared.mem_size = fw_shared_size;225 226 if (amdgpu_vcnfw_log) {227 adev->vcn.inst[i].fw_shared.cpu_addr -= AMDGPU_VCNFW_LOG_SIZE;228 adev->vcn.inst[i].fw_shared.gpu_addr -= AMDGPU_VCNFW_LOG_SIZE;229 adev->vcn.inst[i].fw_shared.log_offset = log_offset;230 }231 232 if (adev->vcn.indirect_sram) {233 r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,234 AMDGPU_GEM_DOMAIN_VRAM |235 AMDGPU_GEM_DOMAIN_GTT,236 &adev->vcn.inst[i].dpg_sram_bo,237 &adev->vcn.inst[i].dpg_sram_gpu_addr,238 &adev->vcn.inst[i].dpg_sram_cpu_addr);239 if (r) {240 dev_err(adev->dev, "VCN %d (%d) failed to allocate DPG bo\n", i, r);241 return r;242 }243 }244 }245 246 return 0;247}248 249int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)250{251 int i, j;252 253 for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {254 if (adev->vcn.harvest_config & (1 << j))255 continue;256 257 amdgpu_bo_free_kernel(258 &adev->vcn.inst[j].dpg_sram_bo,259 &adev->vcn.inst[j].dpg_sram_gpu_addr,260 (void **)&adev->vcn.inst[j].dpg_sram_cpu_addr);261 262 kvfree(adev->vcn.inst[j].saved_bo);263 264 amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,265 &adev->vcn.inst[j].gpu_addr,266 (void **)&adev->vcn.inst[j].cpu_addr);267 268 amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);269 270 for (i = 0; i < adev->vcn.num_enc_rings; ++i)271 amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);272 273 amdgpu_ucode_release(&adev->vcn.fw[j]);274 }275 276 mutex_destroy(&adev->vcn.vcn1_jpeg1_workaround);277 mutex_destroy(&adev->vcn.vcn_pg_lock);278 279 return 0;280}281 282bool amdgpu_vcn_is_disabled_vcn(struct amdgpu_device *adev, enum vcn_ring_type type, uint32_t vcn_instance)283{284 bool ret = false;285 int vcn_config = adev->vcn.vcn_config[vcn_instance];286 287 if ((type == VCN_ENCODE_RING) && (vcn_config & VCN_BLOCK_ENCODE_DISABLE_MASK))288 ret = true;289 else if ((type == VCN_DECODE_RING) && (vcn_config & VCN_BLOCK_DECODE_DISABLE_MASK))290 ret = true;291 else if ((type == VCN_UNIFIED_RING) && (vcn_config & VCN_BLOCK_QUEUE_DISABLE_MASK))292 ret = true;293 294 return ret;295}296 297int amdgpu_vcn_suspend(struct amdgpu_device *adev)298{299 unsigned int size;300 void *ptr;301 int i, idx;302 303 bool in_ras_intr = amdgpu_ras_intr_triggered();304 305 cancel_delayed_work_sync(&adev->vcn.idle_work);306 307 /* err_event_athub will corrupt VCPU buffer, so we need to308 * restore fw data and clear buffer in amdgpu_vcn_resume() */309 if (in_ras_intr)310 return 0;311 312 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {313 if (adev->vcn.harvest_config & (1 << i))314 continue;315 if (adev->vcn.inst[i].vcpu_bo == NULL)316 return 0;317 318 size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);319 ptr = adev->vcn.inst[i].cpu_addr;320 321 adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);322 if (!adev->vcn.inst[i].saved_bo)323 return -ENOMEM;324 325 if (drm_dev_enter(adev_to_drm(adev), &idx)) {326 memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);327 drm_dev_exit(idx);328 }329 }330 return 0;331}332 333int amdgpu_vcn_resume(struct amdgpu_device *adev)334{335 unsigned int size;336 void *ptr;337 int i, idx;338 339 for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {340 if (adev->vcn.harvest_config & (1 << i))341 continue;342 if (adev->vcn.inst[i].vcpu_bo == NULL)343 return -EINVAL;344 345 size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);346 ptr = adev->vcn.inst[i].cpu_addr;347 348 if (adev->vcn.inst[i].saved_bo != NULL) {349 if (drm_dev_enter(adev_to_drm(adev), &idx)) {350 memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);351 drm_dev_exit(idx);352 }353 kvfree(adev->vcn.inst[i].saved_bo);354 adev->vcn.inst[i].saved_bo = NULL;355 } else {356 const struct common_firmware_header *hdr;357 unsigned int offset;358 359 hdr = (const struct common_firmware_header *)adev->vcn.fw[i]->data;360 if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {361 offset = le32_to_cpu(hdr->ucode_array_offset_bytes);362 if (drm_dev_enter(adev_to_drm(adev), &idx)) {363 memcpy_toio(adev->vcn.inst[i].cpu_addr,364 adev->vcn.fw[i]->data + offset,365 le32_to_cpu(hdr->ucode_size_bytes));366 drm_dev_exit(idx);367 }368 size -= le32_to_cpu(hdr->ucode_size_bytes);369 ptr += le32_to_cpu(hdr->ucode_size_bytes);370 }371 memset_io(ptr, 0, size);372 }373 }374 return 0;375}376 377static void amdgpu_vcn_idle_work_handler(struct work_struct *work)378{379 struct amdgpu_device *adev =380 container_of(work, struct amdgpu_device, vcn.idle_work.work);381 unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};382 unsigned int i, j;383 int r = 0;384 385 for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {386 if (adev->vcn.harvest_config & (1 << j))387 continue;388 389 for (i = 0; i < adev->vcn.num_enc_rings; ++i)390 fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);391 392 /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */393 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&394 !adev->vcn.using_unified_queue) {395 struct dpg_pause_state new_state;396 397 if (fence[j] ||398 unlikely(atomic_read(&adev->vcn.inst[j].dpg_enc_submission_cnt)))399 new_state.fw_based = VCN_DPG_STATE__PAUSE;400 else401 new_state.fw_based = VCN_DPG_STATE__UNPAUSE;402 403 adev->vcn.pause_dpg_mode(adev, j, &new_state);404 }405 406 fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);407 fences += fence[j];408 }409 410 if (!fences && !atomic_read(&adev->vcn.total_submission_cnt)) {411 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,412 AMD_PG_STATE_GATE);413 r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,414 false);415 if (r)416 dev_warn(adev->dev, "(%d) failed to disable video power profile mode\n", r);417 } else {418 schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);419 }420}421 422void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)423{424 struct amdgpu_device *adev = ring->adev;425 int r = 0;426 427 atomic_inc(&adev->vcn.total_submission_cnt);428 429 if (!cancel_delayed_work_sync(&adev->vcn.idle_work)) {430 r = amdgpu_dpm_switch_power_profile(adev, PP_SMC_POWER_PROFILE_VIDEO,431 true);432 if (r)433 dev_warn(adev->dev, "(%d) failed to switch to video power profile mode\n", r);434 }435 436 mutex_lock(&adev->vcn.vcn_pg_lock);437 amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,438 AMD_PG_STATE_UNGATE);439 440 /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */441 if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&442 !adev->vcn.using_unified_queue) {443 struct dpg_pause_state new_state;444 445 if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC) {446 atomic_inc(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt);447 new_state.fw_based = VCN_DPG_STATE__PAUSE;448 } else {449 unsigned int fences = 0;450 unsigned int i;451 452 for (i = 0; i < adev->vcn.num_enc_rings; ++i)453 fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);454 455 if (fences || atomic_read(&adev->vcn.inst[ring->me].dpg_enc_submission_cnt))456 new_state.fw_based = VCN_DPG_STATE__PAUSE;457 else458 new_state.fw_based = VCN_DPG_STATE__UNPAUSE;459 }460 461 adev->vcn.pause_dpg_mode(adev, ring->me, &new_state);462 }463 mutex_unlock(&adev->vcn.vcn_pg_lock);464}465 466void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)467{468 struct amdgpu_device *adev = ring->adev;469 470 /* Only set DPG pause for VCN3 or below, VCN4 and above will be handled by FW */471 if (ring->adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG &&472 ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC &&473 !adev->vcn.using_unified_queue)474 atomic_dec(&ring->adev->vcn.inst[ring->me].dpg_enc_submission_cnt);475 476 atomic_dec(&ring->adev->vcn.total_submission_cnt);477 478 schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);479}480 481int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)482{483 struct amdgpu_device *adev = ring->adev;484 uint32_t tmp = 0;485 unsigned int i;486 int r;487 488 /* VCN in SRIOV does not support direct register read/write */489 if (amdgpu_sriov_vf(adev))490 return 0;491 492 WREG32(adev->vcn.inst[ring->me].external.scratch9, 0xCAFEDEAD);493 r = amdgpu_ring_alloc(ring, 3);494 if (r)495 return r;496 amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));497 amdgpu_ring_write(ring, 0xDEADBEEF);498 amdgpu_ring_commit(ring);499 for (i = 0; i < adev->usec_timeout; i++) {500 tmp = RREG32(adev->vcn.inst[ring->me].external.scratch9);501 if (tmp == 0xDEADBEEF)502 break;503 udelay(1);504 }505 506 if (i >= adev->usec_timeout)507 r = -ETIMEDOUT;508 509 return r;510}511 512int amdgpu_vcn_dec_sw_ring_test_ring(struct amdgpu_ring *ring)513{514 struct amdgpu_device *adev = ring->adev;515 uint32_t rptr;516 unsigned int i;517 int r;518 519 if (amdgpu_sriov_vf(adev))520 return 0;521 522 r = amdgpu_ring_alloc(ring, 16);523 if (r)524 return r;525 526 rptr = amdgpu_ring_get_rptr(ring);527 528 amdgpu_ring_write(ring, VCN_DEC_SW_CMD_END);529 amdgpu_ring_commit(ring);530 531 for (i = 0; i < adev->usec_timeout; i++) {532 if (amdgpu_ring_get_rptr(ring) != rptr)533 break;534 udelay(1);535 }536 537 if (i >= adev->usec_timeout)538 r = -ETIMEDOUT;539 540 return r;541}542 543static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,544 struct amdgpu_ib *ib_msg,545 struct dma_fence **fence)546{547 u64 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);548 struct amdgpu_device *adev = ring->adev;549 struct dma_fence *f = NULL;550 struct amdgpu_job *job;551 struct amdgpu_ib *ib;552 int i, r;553 554 r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,555 64, AMDGPU_IB_POOL_DIRECT,556 &job);557 if (r)558 goto err;559 560 ib = &job->ibs[0];561 ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);562 ib->ptr[1] = addr;563 ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);564 ib->ptr[3] = addr >> 32;565 ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);566 ib->ptr[5] = 0;567 for (i = 6; i < 16; i += 2) {568 ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);569 ib->ptr[i+1] = 0;570 }571 ib->length_dw = 16;572 573 r = amdgpu_job_submit_direct(job, ring, &f);574 if (r)575 goto err_free;576 577 amdgpu_ib_free(adev, ib_msg, f);578 579 if (fence)580 *fence = dma_fence_get(f);581 dma_fence_put(f);582 583 return 0;584 585err_free:586 amdgpu_job_free(job);587err:588 amdgpu_ib_free(adev, ib_msg, f);589 return r;590}591 592static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,593 struct amdgpu_ib *ib)594{595 struct amdgpu_device *adev = ring->adev;596 uint32_t *msg;597 int r, i;598 599 memset(ib, 0, sizeof(*ib));600 r = amdgpu_ib_get(adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2,601 AMDGPU_IB_POOL_DIRECT,602 ib);603 if (r)604 return r;605 606 msg = (uint32_t *)AMDGPU_GPU_PAGE_ALIGN((unsigned long)ib->ptr);607 msg[0] = cpu_to_le32(0x00000028);608 msg[1] = cpu_to_le32(0x00000038);609 msg[2] = cpu_to_le32(0x00000001);610 msg[3] = cpu_to_le32(0x00000000);611 msg[4] = cpu_to_le32(handle);612 msg[5] = cpu_to_le32(0x00000000);613 msg[6] = cpu_to_le32(0x00000001);614 msg[7] = cpu_to_le32(0x00000028);615 msg[8] = cpu_to_le32(0x00000010);616 msg[9] = cpu_to_le32(0x00000000);617 msg[10] = cpu_to_le32(0x00000007);618 msg[11] = cpu_to_le32(0x00000000);619 msg[12] = cpu_to_le32(0x00000780);620 msg[13] = cpu_to_le32(0x00000440);621 for (i = 14; i < 1024; ++i)622 msg[i] = cpu_to_le32(0x0);623 624 return 0;625}626 627static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,628 struct amdgpu_ib *ib)629{630 struct amdgpu_device *adev = ring->adev;631 uint32_t *msg;632 int r, i;633 634 memset(ib, 0, sizeof(*ib));635 r = amdgpu_ib_get(adev, NULL, AMDGPU_GPU_PAGE_SIZE * 2,636 AMDGPU_IB_POOL_DIRECT,637 ib);638 if (r)639 return r;640 641 msg = (uint32_t *)AMDGPU_GPU_PAGE_ALIGN((unsigned long)ib->ptr);642 msg[0] = cpu_to_le32(0x00000028);643 msg[1] = cpu_to_le32(0x00000018);644 msg[2] = cpu_to_le32(0x00000000);645 msg[3] = cpu_to_le32(0x00000002);646 msg[4] = cpu_to_le32(handle);647 msg[5] = cpu_to_le32(0x00000000);648 for (i = 6; i < 1024; ++i)649 msg[i] = cpu_to_le32(0x0);650 651 return 0;652}653 654int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)655{656 struct dma_fence *fence = NULL;657 struct amdgpu_ib ib;658 long r;659 660 r = amdgpu_vcn_dec_get_create_msg(ring, 1, &ib);661 if (r)662 goto error;663 664 r = amdgpu_vcn_dec_send_msg(ring, &ib, NULL);665 if (r)666 goto error;667 r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &ib);668 if (r)669 goto error;670 671 r = amdgpu_vcn_dec_send_msg(ring, &ib, &fence);672 if (r)673 goto error;674 675 r = dma_fence_wait_timeout(fence, false, timeout);676 if (r == 0)677 r = -ETIMEDOUT;678 else if (r > 0)679 r = 0;680 681 dma_fence_put(fence);682error:683 return r;684}685 686static uint32_t *amdgpu_vcn_unified_ring_ib_header(struct amdgpu_ib *ib,687 uint32_t ib_pack_in_dw, bool enc)688{689 uint32_t *ib_checksum;690 691 ib->ptr[ib->length_dw++] = 0x00000010; /* single queue checksum */692 ib->ptr[ib->length_dw++] = 0x30000002;693 ib_checksum = &ib->ptr[ib->length_dw++];694 ib->ptr[ib->length_dw++] = ib_pack_in_dw;695 696 ib->ptr[ib->length_dw++] = 0x00000010; /* engine info */697 ib->ptr[ib->length_dw++] = 0x30000001;698 ib->ptr[ib->length_dw++] = enc ? 0x2 : 0x3;699 ib->ptr[ib->length_dw++] = ib_pack_in_dw * sizeof(uint32_t);700 701 return ib_checksum;702}703 704static void amdgpu_vcn_unified_ring_ib_checksum(uint32_t **ib_checksum,705 uint32_t ib_pack_in_dw)706{707 uint32_t i;708 uint32_t checksum = 0;709 710 for (i = 0; i < ib_pack_in_dw; i++)711 checksum += *(*ib_checksum + 2 + i);712 713 **ib_checksum = checksum;714}715 716static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,717 struct amdgpu_ib *ib_msg,718 struct dma_fence **fence)719{720 struct amdgpu_vcn_decode_buffer *decode_buffer = NULL;721 unsigned int ib_size_dw = 64;722 struct amdgpu_device *adev = ring->adev;723 struct dma_fence *f = NULL;724 struct amdgpu_job *job;725 struct amdgpu_ib *ib;726 uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);727 uint32_t *ib_checksum;728 uint32_t ib_pack_in_dw;729 int i, r;730 731 if (adev->vcn.using_unified_queue)732 ib_size_dw += 8;733 734 r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,735 ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,736 &job);737 if (r)738 goto err;739 740 ib = &job->ibs[0];741 ib->length_dw = 0;742 743 /* single queue headers */744 if (adev->vcn.using_unified_queue) {745 ib_pack_in_dw = sizeof(struct amdgpu_vcn_decode_buffer) / sizeof(uint32_t)746 + 4 + 2; /* engine info + decoding ib in dw */747 ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, ib_pack_in_dw, false);748 }749 750 ib->ptr[ib->length_dw++] = sizeof(struct amdgpu_vcn_decode_buffer) + 8;751 ib->ptr[ib->length_dw++] = cpu_to_le32(AMDGPU_VCN_IB_FLAG_DECODE_BUFFER);752 decode_buffer = (struct amdgpu_vcn_decode_buffer *)&(ib->ptr[ib->length_dw]);753 ib->length_dw += sizeof(struct amdgpu_vcn_decode_buffer) / 4;754 memset(decode_buffer, 0, sizeof(struct amdgpu_vcn_decode_buffer));755 756 decode_buffer->valid_buf_flag |= cpu_to_le32(AMDGPU_VCN_CMD_FLAG_MSG_BUFFER);757 decode_buffer->msg_buffer_address_hi = cpu_to_le32(addr >> 32);758 decode_buffer->msg_buffer_address_lo = cpu_to_le32(addr);759 760 for (i = ib->length_dw; i < ib_size_dw; ++i)761 ib->ptr[i] = 0x0;762 763 if (adev->vcn.using_unified_queue)764 amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, ib_pack_in_dw);765 766 r = amdgpu_job_submit_direct(job, ring, &f);767 if (r)768 goto err_free;769 770 amdgpu_ib_free(adev, ib_msg, f);771 772 if (fence)773 *fence = dma_fence_get(f);774 dma_fence_put(f);775 776 return 0;777 778err_free:779 amdgpu_job_free(job);780err:781 amdgpu_ib_free(adev, ib_msg, f);782 return r;783}784 785int amdgpu_vcn_dec_sw_ring_test_ib(struct amdgpu_ring *ring, long timeout)786{787 struct dma_fence *fence = NULL;788 struct amdgpu_ib ib;789 long r;790 791 r = amdgpu_vcn_dec_get_create_msg(ring, 1, &ib);792 if (r)793 goto error;794 795 r = amdgpu_vcn_dec_sw_send_msg(ring, &ib, NULL);796 if (r)797 goto error;798 r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &ib);799 if (r)800 goto error;801 802 r = amdgpu_vcn_dec_sw_send_msg(ring, &ib, &fence);803 if (r)804 goto error;805 806 r = dma_fence_wait_timeout(fence, false, timeout);807 if (r == 0)808 r = -ETIMEDOUT;809 else if (r > 0)810 r = 0;811 812 dma_fence_put(fence);813error:814 return r;815}816 817int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)818{819 struct amdgpu_device *adev = ring->adev;820 uint32_t rptr;821 unsigned int i;822 int r;823 824 if (amdgpu_sriov_vf(adev))825 return 0;826 827 r = amdgpu_ring_alloc(ring, 16);828 if (r)829 return r;830 831 rptr = amdgpu_ring_get_rptr(ring);832 833 amdgpu_ring_write(ring, VCN_ENC_CMD_END);834 amdgpu_ring_commit(ring);835 836 for (i = 0; i < adev->usec_timeout; i++) {837 if (amdgpu_ring_get_rptr(ring) != rptr)838 break;839 udelay(1);840 }841 842 if (i >= adev->usec_timeout)843 r = -ETIMEDOUT;844 845 return r;846}847 848static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,849 struct amdgpu_ib *ib_msg,850 struct dma_fence **fence)851{852 unsigned int ib_size_dw = 16;853 struct amdgpu_device *adev = ring->adev;854 struct amdgpu_job *job;855 struct amdgpu_ib *ib;856 struct dma_fence *f = NULL;857 uint32_t *ib_checksum = NULL;858 uint64_t addr;859 int i, r;860 861 if (adev->vcn.using_unified_queue)862 ib_size_dw += 8;863 864 r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,865 ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,866 &job);867 if (r)868 return r;869 870 ib = &job->ibs[0];871 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);872 873 ib->length_dw = 0;874 875 if (adev->vcn.using_unified_queue)876 ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);877 878 ib->ptr[ib->length_dw++] = 0x00000018;879 ib->ptr[ib->length_dw++] = 0x00000001; /* session info */880 ib->ptr[ib->length_dw++] = handle;881 ib->ptr[ib->length_dw++] = upper_32_bits(addr);882 ib->ptr[ib->length_dw++] = addr;883 ib->ptr[ib->length_dw++] = 0x00000000;884 885 ib->ptr[ib->length_dw++] = 0x00000014;886 ib->ptr[ib->length_dw++] = 0x00000002; /* task info */887 ib->ptr[ib->length_dw++] = 0x0000001c;888 ib->ptr[ib->length_dw++] = 0x00000000;889 ib->ptr[ib->length_dw++] = 0x00000000;890 891 ib->ptr[ib->length_dw++] = 0x00000008;892 ib->ptr[ib->length_dw++] = 0x08000001; /* op initialize */893 894 for (i = ib->length_dw; i < ib_size_dw; ++i)895 ib->ptr[i] = 0x0;896 897 if (adev->vcn.using_unified_queue)898 amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);899 900 r = amdgpu_job_submit_direct(job, ring, &f);901 if (r)902 goto err;903 904 if (fence)905 *fence = dma_fence_get(f);906 dma_fence_put(f);907 908 return 0;909 910err:911 amdgpu_job_free(job);912 return r;913}914 915static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,916 struct amdgpu_ib *ib_msg,917 struct dma_fence **fence)918{919 unsigned int ib_size_dw = 16;920 struct amdgpu_device *adev = ring->adev;921 struct amdgpu_job *job;922 struct amdgpu_ib *ib;923 struct dma_fence *f = NULL;924 uint32_t *ib_checksum = NULL;925 uint64_t addr;926 int i, r;927 928 if (adev->vcn.using_unified_queue)929 ib_size_dw += 8;930 931 r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,932 ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,933 &job);934 if (r)935 return r;936 937 ib = &job->ibs[0];938 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);939 940 ib->length_dw = 0;941 942 if (adev->vcn.using_unified_queue)943 ib_checksum = amdgpu_vcn_unified_ring_ib_header(ib, 0x11, true);944 945 ib->ptr[ib->length_dw++] = 0x00000018;946 ib->ptr[ib->length_dw++] = 0x00000001;947 ib->ptr[ib->length_dw++] = handle;948 ib->ptr[ib->length_dw++] = upper_32_bits(addr);949 ib->ptr[ib->length_dw++] = addr;950 ib->ptr[ib->length_dw++] = 0x00000000;951 952 ib->ptr[ib->length_dw++] = 0x00000014;953 ib->ptr[ib->length_dw++] = 0x00000002;954 ib->ptr[ib->length_dw++] = 0x0000001c;955 ib->ptr[ib->length_dw++] = 0x00000000;956 ib->ptr[ib->length_dw++] = 0x00000000;957 958 ib->ptr[ib->length_dw++] = 0x00000008;959 ib->ptr[ib->length_dw++] = 0x08000002; /* op close session */960 961 for (i = ib->length_dw; i < ib_size_dw; ++i)962 ib->ptr[i] = 0x0;963 964 if (adev->vcn.using_unified_queue)965 amdgpu_vcn_unified_ring_ib_checksum(&ib_checksum, 0x11);966 967 r = amdgpu_job_submit_direct(job, ring, &f);968 if (r)969 goto err;970 971 if (fence)972 *fence = dma_fence_get(f);973 dma_fence_put(f);974 975 return 0;976 977err:978 amdgpu_job_free(job);979 return r;980}981 982int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)983{984 struct amdgpu_device *adev = ring->adev;985 struct dma_fence *fence = NULL;986 struct amdgpu_ib ib;987 long r;988 989 memset(&ib, 0, sizeof(ib));990 r = amdgpu_ib_get(adev, NULL, (128 << 10) + AMDGPU_GPU_PAGE_SIZE,991 AMDGPU_IB_POOL_DIRECT,992 &ib);993 if (r)994 return r;995 996 r = amdgpu_vcn_enc_get_create_msg(ring, 1, &ib, NULL);997 if (r)998 goto error;999 1000 r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, &ib, &fence);1001 if (r)1002 goto error;1003 1004 r = dma_fence_wait_timeout(fence, false, timeout);1005 if (r == 0)1006 r = -ETIMEDOUT;1007 else if (r > 0)1008 r = 0;1009 1010error:1011 amdgpu_ib_free(adev, &ib, fence);1012 dma_fence_put(fence);1013 1014 return r;1015}1016 1017int amdgpu_vcn_unified_ring_test_ib(struct amdgpu_ring *ring, long timeout)1018{1019 struct amdgpu_device *adev = ring->adev;1020 long r;1021 1022 if (amdgpu_ip_version(adev, UVD_HWIP, 0) != IP_VERSION(4, 0, 3)) {1023 r = amdgpu_vcn_enc_ring_test_ib(ring, timeout);1024 if (r)1025 goto error;1026 }1027 1028 r = amdgpu_vcn_dec_sw_ring_test_ib(ring, timeout);1029 1030error:1031 return r;1032}1033 1034enum amdgpu_ring_priority_level amdgpu_vcn_get_enc_ring_prio(int ring)1035{1036 switch (ring) {1037 case 0:1038 return AMDGPU_RING_PRIO_0;1039 case 1:1040 return AMDGPU_RING_PRIO_1;1041 case 2:1042 return AMDGPU_RING_PRIO_2;1043 default:1044 return AMDGPU_RING_PRIO_0;1045 }1046}1047 1048void amdgpu_vcn_setup_ucode(struct amdgpu_device *adev)1049{1050 int i;1051 unsigned int idx;1052 1053 if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {1054 const struct common_firmware_header *hdr;1055 1056 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {1057 if (adev->vcn.harvest_config & (1 << i))1058 continue;1059 1060 hdr = (const struct common_firmware_header *)adev->vcn.fw[i]->data;1061 /* currently only support 2 FW instances */1062 if (i >= 2) {1063 dev_info(adev->dev, "More then 2 VCN FW instances!\n");1064 break;1065 }1066 idx = AMDGPU_UCODE_ID_VCN + i;1067 adev->firmware.ucode[idx].ucode_id = idx;1068 adev->firmware.ucode[idx].fw = adev->vcn.fw[i];1069 adev->firmware.fw_size +=1070 ALIGN(le32_to_cpu(hdr->ucode_size_bytes), PAGE_SIZE);1071 1072 if (amdgpu_ip_version(adev, UVD_HWIP, 0) ==1073 IP_VERSION(4, 0, 3))1074 break;1075 }1076 }1077}1078 1079/*1080 * debugfs for mapping vcn firmware log buffer.1081 */1082#if defined(CONFIG_DEBUG_FS)1083static ssize_t amdgpu_debugfs_vcn_fwlog_read(struct file *f, char __user *buf,1084 size_t size, loff_t *pos)1085{1086 struct amdgpu_vcn_inst *vcn;1087 void *log_buf;1088 volatile struct amdgpu_vcn_fwlog *plog;1089 unsigned int read_pos, write_pos, available, i, read_bytes = 0;1090 unsigned int read_num[2] = {0};1091 1092 vcn = file_inode(f)->i_private;1093 if (!vcn)1094 return -ENODEV;1095 1096 if (!vcn->fw_shared.cpu_addr || !amdgpu_vcnfw_log)1097 return -EFAULT;1098 1099 log_buf = vcn->fw_shared.cpu_addr + vcn->fw_shared.mem_size;1100 1101 plog = (volatile struct amdgpu_vcn_fwlog *)log_buf;1102 read_pos = plog->rptr;1103 write_pos = plog->wptr;1104 1105 if (read_pos > AMDGPU_VCNFW_LOG_SIZE || write_pos > AMDGPU_VCNFW_LOG_SIZE)1106 return -EFAULT;1107 1108 if (!size || (read_pos == write_pos))1109 return 0;1110 1111 if (write_pos > read_pos) {1112 available = write_pos - read_pos;1113 read_num[0] = min_t(size_t, size, available);1114 } else {1115 read_num[0] = AMDGPU_VCNFW_LOG_SIZE - read_pos;1116 available = read_num[0] + write_pos - plog->header_size;1117 if (size > available)1118 read_num[1] = write_pos - plog->header_size;1119 else if (size > read_num[0])1120 read_num[1] = size - read_num[0];1121 else1122 read_num[0] = size;1123 }1124 1125 for (i = 0; i < 2; i++) {1126 if (read_num[i]) {1127 if (read_pos == AMDGPU_VCNFW_LOG_SIZE)1128 read_pos = plog->header_size;1129 if (read_num[i] == copy_to_user((buf + read_bytes),1130 (log_buf + read_pos), read_num[i]))1131 return -EFAULT;1132 1133 read_bytes += read_num[i];1134 read_pos += read_num[i];1135 }1136 }1137 1138 plog->rptr = read_pos;1139 *pos += read_bytes;1140 return read_bytes;1141}1142 1143static const struct file_operations amdgpu_debugfs_vcnfwlog_fops = {1144 .owner = THIS_MODULE,1145 .read = amdgpu_debugfs_vcn_fwlog_read,1146 .llseek = default_llseek1147};1148#endif1149 1150void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, uint8_t i,1151 struct amdgpu_vcn_inst *vcn)1152{1153#if defined(CONFIG_DEBUG_FS)1154 struct drm_minor *minor = adev_to_drm(adev)->primary;1155 struct dentry *root = minor->debugfs_root;1156 char name[32];1157 1158 sprintf(name, "amdgpu_vcn_%d_fwlog", i);1159 debugfs_create_file_size(name, S_IFREG | 0444, root, vcn,1160 &amdgpu_debugfs_vcnfwlog_fops,1161 AMDGPU_VCNFW_LOG_SIZE);1162#endif1163}1164 1165void amdgpu_vcn_fwlog_init(struct amdgpu_vcn_inst *vcn)1166{1167#if defined(CONFIG_DEBUG_FS)1168 volatile uint32_t *flag = vcn->fw_shared.cpu_addr;1169 void *fw_log_cpu_addr = vcn->fw_shared.cpu_addr + vcn->fw_shared.mem_size;1170 uint64_t fw_log_gpu_addr = vcn->fw_shared.gpu_addr + vcn->fw_shared.mem_size;1171 volatile struct amdgpu_vcn_fwlog *log_buf = fw_log_cpu_addr;1172 volatile struct amdgpu_fw_shared_fw_logging *fw_log = vcn->fw_shared.cpu_addr1173 + vcn->fw_shared.log_offset;1174 *flag |= cpu_to_le32(AMDGPU_VCN_FW_LOGGING_FLAG);1175 fw_log->is_enabled = 1;1176 fw_log->addr_lo = cpu_to_le32(fw_log_gpu_addr & 0xFFFFFFFF);1177 fw_log->addr_hi = cpu_to_le32(fw_log_gpu_addr >> 32);1178 fw_log->size = cpu_to_le32(AMDGPU_VCNFW_LOG_SIZE);1179 1180 log_buf->header_size = sizeof(struct amdgpu_vcn_fwlog);1181 log_buf->buffer_size = AMDGPU_VCNFW_LOG_SIZE;1182 log_buf->rptr = log_buf->header_size;1183 log_buf->wptr = log_buf->header_size;1184 log_buf->wrapped = 0;1185#endif1186}1187 1188int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,1189 struct amdgpu_irq_src *source,1190 struct amdgpu_iv_entry *entry)1191{1192 struct ras_common_if *ras_if = adev->vcn.ras_if;1193 struct ras_dispatch_if ih_data = {1194 .entry = entry,1195 };1196 1197 if (!ras_if)1198 return 0;1199 1200 if (!amdgpu_sriov_vf(adev)) {1201 ih_data.head = *ras_if;1202 amdgpu_ras_interrupt_dispatch(adev, &ih_data);1203 } else {1204 if (adev->virt.ops && adev->virt.ops->ras_poison_handler)1205 adev->virt.ops->ras_poison_handler(adev, ras_if->block);1206 else1207 dev_warn(adev->dev,1208 "No ras_poison_handler interface in SRIOV for VCN!\n");1209 }1210 1211 return 0;1212}1213 1214int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)1215{1216 int r, i;1217 1218 r = amdgpu_ras_block_late_init(adev, ras_block);1219 if (r)1220 return r;1221 1222 if (amdgpu_ras_is_supported(adev, ras_block->block)) {1223 for (i = 0; i < adev->vcn.num_vcn_inst; i++) {1224 if (adev->vcn.harvest_config & (1 << i) ||1225 !adev->vcn.inst[i].ras_poison_irq.funcs)1226 continue;1227 1228 r = amdgpu_irq_get(adev, &adev->vcn.inst[i].ras_poison_irq, 0);1229 if (r)1230 goto late_fini;1231 }1232 }1233 return 0;1234 1235late_fini:1236 amdgpu_ras_block_late_fini(adev, ras_block);1237 return r;1238}1239 1240int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev)1241{1242 int err;1243 struct amdgpu_vcn_ras *ras;1244 1245 if (!adev->vcn.ras)1246 return 0;1247 1248 ras = adev->vcn.ras;1249 err = amdgpu_ras_register_ras_block(adev, &ras->ras_block);1250 if (err) {1251 dev_err(adev->dev, "Failed to register vcn ras block!\n");1252 return err;1253 }1254 1255 strcpy(ras->ras_block.ras_comm.name, "vcn");1256 ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN;1257 ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;1258 adev->vcn.ras_if = &ras->ras_block.ras_comm;1259 1260 if (!ras->ras_block.ras_late_init)1261 ras->ras_block.ras_late_init = amdgpu_vcn_ras_late_init;1262 1263 return 0;1264}1265 1266int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,1267 enum AMDGPU_UCODE_ID ucode_id)1268{1269 struct amdgpu_firmware_info ucode = {1270 .ucode_id = (ucode_id ? ucode_id :1271 (inst_idx ? AMDGPU_UCODE_ID_VCN1_RAM :1272 AMDGPU_UCODE_ID_VCN0_RAM)),1273 .mc_addr = adev->vcn.inst[inst_idx].dpg_sram_gpu_addr,1274 .ucode_size = ((uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_curr_addr -1275 (uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr),1276 };1277 1278 return psp_execute_ip_fw_load(&adev->psp, &ucode);1279}1280