linux/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
<<
>>
Prefs
   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 a
   6 * copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sub license, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
  16 * 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 OR
  18 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
  20 *
  21 * The above copyright notice and this permission notice (including the
  22 * next paragraph) shall be included in all copies or substantial portions
  23 * of the Software.
  24 *
  25 */
  26
  27#include <linux/firmware.h>
  28#include <linux/module.h>
  29#include <linux/pci.h>
  30
  31#include <drm/drm.h>
  32
  33#include "amdgpu.h"
  34#include "amdgpu_pm.h"
  35#include "amdgpu_vcn.h"
  36#include "soc15d.h"
  37#include "soc15_common.h"
  38
  39#include "vcn/vcn_1_0_offset.h"
  40#include "vcn/vcn_1_0_sh_mask.h"
  41
  42/* 1 second timeout */
  43#define VCN_IDLE_TIMEOUT        msecs_to_jiffies(1000)
  44
  45/* Firmware Names */
  46#define FIRMWARE_RAVEN          "amdgpu/raven_vcn.bin"
  47#define FIRMWARE_PICASSO        "amdgpu/picasso_vcn.bin"
  48#define FIRMWARE_RAVEN2         "amdgpu/raven2_vcn.bin"
  49#define FIRMWARE_ARCTURUS       "amdgpu/arcturus_vcn.bin"
  50#define FIRMWARE_RENOIR         "amdgpu/renoir_vcn.bin"
  51#define FIRMWARE_NAVI10         "amdgpu/navi10_vcn.bin"
  52#define FIRMWARE_NAVI14         "amdgpu/navi14_vcn.bin"
  53#define FIRMWARE_NAVI12         "amdgpu/navi12_vcn.bin"
  54
  55MODULE_FIRMWARE(FIRMWARE_RAVEN);
  56MODULE_FIRMWARE(FIRMWARE_PICASSO);
  57MODULE_FIRMWARE(FIRMWARE_RAVEN2);
  58MODULE_FIRMWARE(FIRMWARE_ARCTURUS);
  59MODULE_FIRMWARE(FIRMWARE_RENOIR);
  60MODULE_FIRMWARE(FIRMWARE_NAVI10);
  61MODULE_FIRMWARE(FIRMWARE_NAVI14);
  62MODULE_FIRMWARE(FIRMWARE_NAVI12);
  63
  64static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
  65
  66int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
  67{
  68        unsigned long bo_size;
  69        const char *fw_name;
  70        const struct common_firmware_header *hdr;
  71        unsigned char fw_check;
  72        int i, r;
  73
  74        INIT_DELAYED_WORK(&adev->vcn.idle_work, amdgpu_vcn_idle_work_handler);
  75
  76        switch (adev->asic_type) {
  77        case CHIP_RAVEN:
  78                if (adev->rev_id >= 8)
  79                        fw_name = FIRMWARE_RAVEN2;
  80                else if (adev->pdev->device == 0x15d8)
  81                        fw_name = FIRMWARE_PICASSO;
  82                else
  83                        fw_name = FIRMWARE_RAVEN;
  84                break;
  85        case CHIP_ARCTURUS:
  86                fw_name = FIRMWARE_ARCTURUS;
  87                break;
  88        case CHIP_RENOIR:
  89                fw_name = FIRMWARE_RENOIR;
  90                if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
  91                    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
  92                        adev->vcn.indirect_sram = true;
  93                break;
  94        case CHIP_NAVI10:
  95                fw_name = FIRMWARE_NAVI10;
  96                if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
  97                    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
  98                        adev->vcn.indirect_sram = true;
  99                break;
 100        case CHIP_NAVI14:
 101                fw_name = FIRMWARE_NAVI14;
 102                if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
 103                    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
 104                        adev->vcn.indirect_sram = true;
 105                break;
 106        case CHIP_NAVI12:
 107                fw_name = FIRMWARE_NAVI12;
 108                if ((adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) &&
 109                    (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG))
 110                        adev->vcn.indirect_sram = true;
 111                break;
 112        default:
 113                return -EINVAL;
 114        }
 115
 116        r = request_firmware(&adev->vcn.fw, fw_name, adev->dev);
 117        if (r) {
 118                dev_err(adev->dev, "amdgpu_vcn: Can't load firmware \"%s\"\n",
 119                        fw_name);
 120                return r;
 121        }
 122
 123        r = amdgpu_ucode_validate(adev->vcn.fw);
 124        if (r) {
 125                dev_err(adev->dev, "amdgpu_vcn: Can't validate firmware \"%s\"\n",
 126                        fw_name);
 127                release_firmware(adev->vcn.fw);
 128                adev->vcn.fw = NULL;
 129                return r;
 130        }
 131
 132        hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
 133        adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
 134
 135        /* Bit 20-23, it is encode major and non-zero for new naming convention.
 136         * This field is part of version minor and DRM_DISABLED_FLAG in old naming
 137         * convention. Since the l:wq!atest version minor is 0x5B and DRM_DISABLED_FLAG
 138         * is zero in old naming convention, this field is always zero so far.
 139         * These four bits are used to tell which naming convention is present.
 140         */
 141        fw_check = (le32_to_cpu(hdr->ucode_version) >> 20) & 0xf;
 142        if (fw_check) {
 143                unsigned int dec_ver, enc_major, enc_minor, vep, fw_rev;
 144
 145                fw_rev = le32_to_cpu(hdr->ucode_version) & 0xfff;
 146                enc_minor = (le32_to_cpu(hdr->ucode_version) >> 12) & 0xff;
 147                enc_major = fw_check;
 148                dec_ver = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xf;
 149                vep = (le32_to_cpu(hdr->ucode_version) >> 28) & 0xf;
 150                DRM_INFO("Found VCN firmware Version ENC: %hu.%hu DEC: %hu VEP: %hu Revision: %hu\n",
 151                        enc_major, enc_minor, dec_ver, vep, fw_rev);
 152        } else {
 153                unsigned int version_major, version_minor, family_id;
 154
 155                family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
 156                version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
 157                version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
 158                DRM_INFO("Found VCN firmware Version: %hu.%hu Family ID: %hu\n",
 159                        version_major, version_minor, family_id);
 160        }
 161
 162        bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
 163        if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
 164                bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
 165
 166        for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
 167                if (adev->vcn.harvest_config & (1 << i))
 168                        continue;
 169
 170                r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
 171                                                AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.inst[i].vcpu_bo,
 172                                                &adev->vcn.inst[i].gpu_addr, &adev->vcn.inst[i].cpu_addr);
 173                if (r) {
 174                        dev_err(adev->dev, "(%d) failed to allocate vcn bo\n", r);
 175                        return r;
 176                }
 177        }
 178
 179        if (adev->vcn.indirect_sram) {
 180                r = amdgpu_bo_create_kernel(adev, 64 * 2 * 4, PAGE_SIZE,
 181                            AMDGPU_GEM_DOMAIN_VRAM, &adev->vcn.dpg_sram_bo,
 182                            &adev->vcn.dpg_sram_gpu_addr, &adev->vcn.dpg_sram_cpu_addr);
 183                if (r) {
 184                        dev_err(adev->dev, "(%d) failed to allocate DPG bo\n", r);
 185                        return r;
 186                }
 187        }
 188
 189        return 0;
 190}
 191
 192int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
 193{
 194        int i, j;
 195
 196        if (adev->vcn.indirect_sram) {
 197                amdgpu_bo_free_kernel(&adev->vcn.dpg_sram_bo,
 198                                      &adev->vcn.dpg_sram_gpu_addr,
 199                                      (void **)&adev->vcn.dpg_sram_cpu_addr);
 200        }
 201
 202        for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
 203                if (adev->vcn.harvest_config & (1 << j))
 204                        continue;
 205                kvfree(adev->vcn.inst[j].saved_bo);
 206
 207                amdgpu_bo_free_kernel(&adev->vcn.inst[j].vcpu_bo,
 208                                          &adev->vcn.inst[j].gpu_addr,
 209                                          (void **)&adev->vcn.inst[j].cpu_addr);
 210
 211                amdgpu_ring_fini(&adev->vcn.inst[j].ring_dec);
 212
 213                for (i = 0; i < adev->vcn.num_enc_rings; ++i)
 214                        amdgpu_ring_fini(&adev->vcn.inst[j].ring_enc[i]);
 215
 216                amdgpu_ring_fini(&adev->vcn.inst[j].ring_jpeg);
 217        }
 218
 219        release_firmware(adev->vcn.fw);
 220
 221        return 0;
 222}
 223
 224int amdgpu_vcn_suspend(struct amdgpu_device *adev)
 225{
 226        unsigned size;
 227        void *ptr;
 228        int i;
 229
 230        cancel_delayed_work_sync(&adev->vcn.idle_work);
 231
 232        for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 233                if (adev->vcn.harvest_config & (1 << i))
 234                        continue;
 235                if (adev->vcn.inst[i].vcpu_bo == NULL)
 236                        return 0;
 237
 238                size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
 239                ptr = adev->vcn.inst[i].cpu_addr;
 240
 241                adev->vcn.inst[i].saved_bo = kvmalloc(size, GFP_KERNEL);
 242                if (!adev->vcn.inst[i].saved_bo)
 243                        return -ENOMEM;
 244
 245                memcpy_fromio(adev->vcn.inst[i].saved_bo, ptr, size);
 246        }
 247        return 0;
 248}
 249
 250int amdgpu_vcn_resume(struct amdgpu_device *adev)
 251{
 252        unsigned size;
 253        void *ptr;
 254        int i;
 255
 256        for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
 257                if (adev->vcn.harvest_config & (1 << i))
 258                        continue;
 259                if (adev->vcn.inst[i].vcpu_bo == NULL)
 260                        return -EINVAL;
 261
 262                size = amdgpu_bo_size(adev->vcn.inst[i].vcpu_bo);
 263                ptr = adev->vcn.inst[i].cpu_addr;
 264
 265                if (adev->vcn.inst[i].saved_bo != NULL) {
 266                        memcpy_toio(ptr, adev->vcn.inst[i].saved_bo, size);
 267                        kvfree(adev->vcn.inst[i].saved_bo);
 268                        adev->vcn.inst[i].saved_bo = NULL;
 269                } else {
 270                        const struct common_firmware_header *hdr;
 271                        unsigned offset;
 272
 273                        hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
 274                        if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
 275                                offset = le32_to_cpu(hdr->ucode_array_offset_bytes);
 276                                memcpy_toio(adev->vcn.inst[i].cpu_addr, adev->vcn.fw->data + offset,
 277                                            le32_to_cpu(hdr->ucode_size_bytes));
 278                                size -= le32_to_cpu(hdr->ucode_size_bytes);
 279                                ptr += le32_to_cpu(hdr->ucode_size_bytes);
 280                        }
 281                        memset_io(ptr, 0, size);
 282                }
 283        }
 284        return 0;
 285}
 286
 287static void amdgpu_vcn_idle_work_handler(struct work_struct *work)
 288{
 289        struct amdgpu_device *adev =
 290                container_of(work, struct amdgpu_device, vcn.idle_work.work);
 291        unsigned int fences = 0, fence[AMDGPU_MAX_VCN_INSTANCES] = {0};
 292        unsigned int i, j;
 293
 294        for (j = 0; j < adev->vcn.num_vcn_inst; ++j) {
 295                if (adev->vcn.harvest_config & (1 << j))
 296                        continue;
 297                for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
 298                        fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_enc[i]);
 299                }
 300
 301                if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)    {
 302                        struct dpg_pause_state new_state;
 303
 304                        if (fence[j])
 305                                new_state.fw_based = VCN_DPG_STATE__PAUSE;
 306                        else
 307                                new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 308
 309                        if (amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_jpeg))
 310                                new_state.jpeg = VCN_DPG_STATE__PAUSE;
 311                        else
 312                                new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
 313
 314                        adev->vcn.pause_dpg_mode(adev, &new_state);
 315                }
 316
 317                fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_jpeg);
 318                fence[j] += amdgpu_fence_count_emitted(&adev->vcn.inst[j].ring_dec);
 319                fences += fence[j];
 320        }
 321
 322        if (fences == 0) {
 323                amdgpu_gfx_off_ctrl(adev, true);
 324                if (adev->asic_type < CHIP_ARCTURUS && adev->pm.dpm_enabled)
 325                        amdgpu_dpm_enable_uvd(adev, false);
 326                else
 327                        amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
 328                                                               AMD_PG_STATE_GATE);
 329        } else {
 330                schedule_delayed_work(&adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
 331        }
 332}
 333
 334void amdgpu_vcn_ring_begin_use(struct amdgpu_ring *ring)
 335{
 336        struct amdgpu_device *adev = ring->adev;
 337        bool set_clocks = !cancel_delayed_work_sync(&adev->vcn.idle_work);
 338
 339        if (set_clocks) {
 340                amdgpu_gfx_off_ctrl(adev, false);
 341                if (adev->asic_type < CHIP_ARCTURUS && adev->pm.dpm_enabled)
 342                        amdgpu_dpm_enable_uvd(adev, true);
 343                else
 344                        amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCN,
 345                                                               AMD_PG_STATE_UNGATE);
 346        }
 347
 348        if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)    {
 349                struct dpg_pause_state new_state;
 350                unsigned int fences = 0;
 351                unsigned int i;
 352
 353                for (i = 0; i < adev->vcn.num_enc_rings; ++i) {
 354                        fences += amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_enc[i]);
 355                }
 356                if (fences)
 357                        new_state.fw_based = VCN_DPG_STATE__PAUSE;
 358                else
 359                        new_state.fw_based = VCN_DPG_STATE__UNPAUSE;
 360
 361                if (amdgpu_fence_count_emitted(&adev->vcn.inst[ring->me].ring_jpeg))
 362                        new_state.jpeg = VCN_DPG_STATE__PAUSE;
 363                else
 364                        new_state.jpeg = VCN_DPG_STATE__UNPAUSE;
 365
 366                if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC)
 367                        new_state.fw_based = VCN_DPG_STATE__PAUSE;
 368                else if (ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG)
 369                        new_state.jpeg = VCN_DPG_STATE__PAUSE;
 370
 371                adev->vcn.pause_dpg_mode(adev, &new_state);
 372        }
 373}
 374
 375void amdgpu_vcn_ring_end_use(struct amdgpu_ring *ring)
 376{
 377        schedule_delayed_work(&ring->adev->vcn.idle_work, VCN_IDLE_TIMEOUT);
 378}
 379
 380int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
 381{
 382        struct amdgpu_device *adev = ring->adev;
 383        uint32_t tmp = 0;
 384        unsigned i;
 385        int r;
 386
 387        WREG32(adev->vcn.inst[ring->me].external.scratch9, 0xCAFEDEAD);
 388        r = amdgpu_ring_alloc(ring, 3);
 389        if (r)
 390                return r;
 391        amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.scratch9, 0));
 392        amdgpu_ring_write(ring, 0xDEADBEEF);
 393        amdgpu_ring_commit(ring);
 394        for (i = 0; i < adev->usec_timeout; i++) {
 395                tmp = RREG32(adev->vcn.inst[ring->me].external.scratch9);
 396                if (tmp == 0xDEADBEEF)
 397                        break;
 398                udelay(1);
 399        }
 400
 401        if (i >= adev->usec_timeout)
 402                r = -ETIMEDOUT;
 403
 404        return r;
 405}
 406
 407static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
 408                                   struct amdgpu_bo *bo,
 409                                   struct dma_fence **fence)
 410{
 411        struct amdgpu_device *adev = ring->adev;
 412        struct dma_fence *f = NULL;
 413        struct amdgpu_job *job;
 414        struct amdgpu_ib *ib;
 415        uint64_t addr;
 416        int i, r;
 417
 418        r = amdgpu_job_alloc_with_ib(adev, 64, &job);
 419        if (r)
 420                goto err;
 421
 422        ib = &job->ibs[0];
 423        addr = amdgpu_bo_gpu_offset(bo);
 424        ib->ptr[0] = PACKET0(adev->vcn.internal.data0, 0);
 425        ib->ptr[1] = addr;
 426        ib->ptr[2] = PACKET0(adev->vcn.internal.data1, 0);
 427        ib->ptr[3] = addr >> 32;
 428        ib->ptr[4] = PACKET0(adev->vcn.internal.cmd, 0);
 429        ib->ptr[5] = 0;
 430        for (i = 6; i < 16; i += 2) {
 431                ib->ptr[i] = PACKET0(adev->vcn.internal.nop, 0);
 432                ib->ptr[i+1] = 0;
 433        }
 434        ib->length_dw = 16;
 435
 436        r = amdgpu_job_submit_direct(job, ring, &f);
 437        if (r)
 438                goto err_free;
 439
 440        amdgpu_bo_fence(bo, f, false);
 441        amdgpu_bo_unreserve(bo);
 442        amdgpu_bo_unref(&bo);
 443
 444        if (fence)
 445                *fence = dma_fence_get(f);
 446        dma_fence_put(f);
 447
 448        return 0;
 449
 450err_free:
 451        amdgpu_job_free(job);
 452
 453err:
 454        amdgpu_bo_unreserve(bo);
 455        amdgpu_bo_unref(&bo);
 456        return r;
 457}
 458
 459static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
 460                              struct dma_fence **fence)
 461{
 462        struct amdgpu_device *adev = ring->adev;
 463        struct amdgpu_bo *bo = NULL;
 464        uint32_t *msg;
 465        int r, i;
 466
 467        r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
 468                                      AMDGPU_GEM_DOMAIN_VRAM,
 469                                      &bo, NULL, (void **)&msg);
 470        if (r)
 471                return r;
 472
 473        msg[0] = cpu_to_le32(0x00000028);
 474        msg[1] = cpu_to_le32(0x00000038);
 475        msg[2] = cpu_to_le32(0x00000001);
 476        msg[3] = cpu_to_le32(0x00000000);
 477        msg[4] = cpu_to_le32(handle);
 478        msg[5] = cpu_to_le32(0x00000000);
 479        msg[6] = cpu_to_le32(0x00000001);
 480        msg[7] = cpu_to_le32(0x00000028);
 481        msg[8] = cpu_to_le32(0x00000010);
 482        msg[9] = cpu_to_le32(0x00000000);
 483        msg[10] = cpu_to_le32(0x00000007);
 484        msg[11] = cpu_to_le32(0x00000000);
 485        msg[12] = cpu_to_le32(0x00000780);
 486        msg[13] = cpu_to_le32(0x00000440);
 487        for (i = 14; i < 1024; ++i)
 488                msg[i] = cpu_to_le32(0x0);
 489
 490        return amdgpu_vcn_dec_send_msg(ring, bo, fence);
 491}
 492
 493static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
 494                               struct dma_fence **fence)
 495{
 496        struct amdgpu_device *adev = ring->adev;
 497        struct amdgpu_bo *bo = NULL;
 498        uint32_t *msg;
 499        int r, i;
 500
 501        r = amdgpu_bo_create_reserved(adev, 1024, PAGE_SIZE,
 502                                      AMDGPU_GEM_DOMAIN_VRAM,
 503                                      &bo, NULL, (void **)&msg);
 504        if (r)
 505                return r;
 506
 507        msg[0] = cpu_to_le32(0x00000028);
 508        msg[1] = cpu_to_le32(0x00000018);
 509        msg[2] = cpu_to_le32(0x00000000);
 510        msg[3] = cpu_to_le32(0x00000002);
 511        msg[4] = cpu_to_le32(handle);
 512        msg[5] = cpu_to_le32(0x00000000);
 513        for (i = 6; i < 1024; ++i)
 514                msg[i] = cpu_to_le32(0x0);
 515
 516        return amdgpu_vcn_dec_send_msg(ring, bo, fence);
 517}
 518
 519int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 520{
 521        struct dma_fence *fence;
 522        long r;
 523
 524        r = amdgpu_vcn_dec_get_create_msg(ring, 1, NULL);
 525        if (r)
 526                goto error;
 527
 528        r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &fence);
 529        if (r)
 530                goto error;
 531
 532        r = dma_fence_wait_timeout(fence, false, timeout);
 533        if (r == 0)
 534                r = -ETIMEDOUT;
 535        else if (r > 0)
 536                r = 0;
 537
 538        dma_fence_put(fence);
 539error:
 540        return r;
 541}
 542
 543int amdgpu_vcn_enc_ring_test_ring(struct amdgpu_ring *ring)
 544{
 545        struct amdgpu_device *adev = ring->adev;
 546        uint32_t rptr;
 547        unsigned i;
 548        int r;
 549
 550        r = amdgpu_ring_alloc(ring, 16);
 551        if (r)
 552                return r;
 553
 554        rptr = amdgpu_ring_get_rptr(ring);
 555
 556        amdgpu_ring_write(ring, VCN_ENC_CMD_END);
 557        amdgpu_ring_commit(ring);
 558
 559        for (i = 0; i < adev->usec_timeout; i++) {
 560                if (amdgpu_ring_get_rptr(ring) != rptr)
 561                        break;
 562                udelay(1);
 563        }
 564
 565        if (i >= adev->usec_timeout)
 566                r = -ETIMEDOUT;
 567
 568        return r;
 569}
 570
 571static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
 572                                         struct amdgpu_bo *bo,
 573                                         struct dma_fence **fence)
 574{
 575        const unsigned ib_size_dw = 16;
 576        struct amdgpu_job *job;
 577        struct amdgpu_ib *ib;
 578        struct dma_fence *f = NULL;
 579        uint64_t addr;
 580        int i, r;
 581
 582        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
 583        if (r)
 584                return r;
 585
 586        ib = &job->ibs[0];
 587        addr = amdgpu_bo_gpu_offset(bo);
 588
 589        ib->length_dw = 0;
 590        ib->ptr[ib->length_dw++] = 0x00000018;
 591        ib->ptr[ib->length_dw++] = 0x00000001; /* session info */
 592        ib->ptr[ib->length_dw++] = handle;
 593        ib->ptr[ib->length_dw++] = upper_32_bits(addr);
 594        ib->ptr[ib->length_dw++] = addr;
 595        ib->ptr[ib->length_dw++] = 0x0000000b;
 596
 597        ib->ptr[ib->length_dw++] = 0x00000014;
 598        ib->ptr[ib->length_dw++] = 0x00000002; /* task info */
 599        ib->ptr[ib->length_dw++] = 0x0000001c;
 600        ib->ptr[ib->length_dw++] = 0x00000000;
 601        ib->ptr[ib->length_dw++] = 0x00000000;
 602
 603        ib->ptr[ib->length_dw++] = 0x00000008;
 604        ib->ptr[ib->length_dw++] = 0x08000001; /* op initialize */
 605
 606        for (i = ib->length_dw; i < ib_size_dw; ++i)
 607                ib->ptr[i] = 0x0;
 608
 609        r = amdgpu_job_submit_direct(job, ring, &f);
 610        if (r)
 611                goto err;
 612
 613        if (fence)
 614                *fence = dma_fence_get(f);
 615        dma_fence_put(f);
 616
 617        return 0;
 618
 619err:
 620        amdgpu_job_free(job);
 621        return r;
 622}
 623
 624static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
 625                                          struct amdgpu_bo *bo,
 626                                          struct dma_fence **fence)
 627{
 628        const unsigned ib_size_dw = 16;
 629        struct amdgpu_job *job;
 630        struct amdgpu_ib *ib;
 631        struct dma_fence *f = NULL;
 632        uint64_t addr;
 633        int i, r;
 634
 635        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
 636        if (r)
 637                return r;
 638
 639        ib = &job->ibs[0];
 640        addr = amdgpu_bo_gpu_offset(bo);
 641
 642        ib->length_dw = 0;
 643        ib->ptr[ib->length_dw++] = 0x00000018;
 644        ib->ptr[ib->length_dw++] = 0x00000001;
 645        ib->ptr[ib->length_dw++] = handle;
 646        ib->ptr[ib->length_dw++] = upper_32_bits(addr);
 647        ib->ptr[ib->length_dw++] = addr;
 648        ib->ptr[ib->length_dw++] = 0x0000000b;
 649
 650        ib->ptr[ib->length_dw++] = 0x00000014;
 651        ib->ptr[ib->length_dw++] = 0x00000002;
 652        ib->ptr[ib->length_dw++] = 0x0000001c;
 653        ib->ptr[ib->length_dw++] = 0x00000000;
 654        ib->ptr[ib->length_dw++] = 0x00000000;
 655
 656        ib->ptr[ib->length_dw++] = 0x00000008;
 657        ib->ptr[ib->length_dw++] = 0x08000002; /* op close session */
 658
 659        for (i = ib->length_dw; i < ib_size_dw; ++i)
 660                ib->ptr[i] = 0x0;
 661
 662        r = amdgpu_job_submit_direct(job, ring, &f);
 663        if (r)
 664                goto err;
 665
 666        if (fence)
 667                *fence = dma_fence_get(f);
 668        dma_fence_put(f);
 669
 670        return 0;
 671
 672err:
 673        amdgpu_job_free(job);
 674        return r;
 675}
 676
 677int amdgpu_vcn_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 678{
 679        struct dma_fence *fence = NULL;
 680        struct amdgpu_bo *bo = NULL;
 681        long r;
 682
 683        r = amdgpu_bo_create_reserved(ring->adev, 128 * 1024, PAGE_SIZE,
 684                                      AMDGPU_GEM_DOMAIN_VRAM,
 685                                      &bo, NULL, NULL);
 686        if (r)
 687                return r;
 688
 689        r = amdgpu_vcn_enc_get_create_msg(ring, 1, bo, NULL);
 690        if (r)
 691                goto error;
 692
 693        r = amdgpu_vcn_enc_get_destroy_msg(ring, 1, bo, &fence);
 694        if (r)
 695                goto error;
 696
 697        r = dma_fence_wait_timeout(fence, false, timeout);
 698        if (r == 0)
 699                r = -ETIMEDOUT;
 700        else if (r > 0)
 701                r = 0;
 702
 703error:
 704        dma_fence_put(fence);
 705        amdgpu_bo_unreserve(bo);
 706        amdgpu_bo_unref(&bo);
 707        return r;
 708}
 709
 710int amdgpu_vcn_jpeg_ring_test_ring(struct amdgpu_ring *ring)
 711{
 712        struct amdgpu_device *adev = ring->adev;
 713        uint32_t tmp = 0;
 714        unsigned i;
 715        int r;
 716
 717        WREG32(adev->vcn.inst[ring->me].external.jpeg_pitch, 0xCAFEDEAD);
 718        r = amdgpu_ring_alloc(ring, 3);
 719        if (r)
 720                return r;
 721
 722        amdgpu_ring_write(ring, PACKET0(adev->vcn.internal.jpeg_pitch, 0));
 723        amdgpu_ring_write(ring, 0xDEADBEEF);
 724        amdgpu_ring_commit(ring);
 725
 726        for (i = 0; i < adev->usec_timeout; i++) {
 727                tmp = RREG32(adev->vcn.inst[ring->me].external.jpeg_pitch);
 728                if (tmp == 0xDEADBEEF)
 729                        break;
 730                udelay(1);
 731        }
 732
 733        if (i >= adev->usec_timeout)
 734                r = -ETIMEDOUT;
 735
 736        return r;
 737}
 738
 739static int amdgpu_vcn_jpeg_set_reg(struct amdgpu_ring *ring, uint32_t handle,
 740                struct dma_fence **fence)
 741{
 742        struct amdgpu_device *adev = ring->adev;
 743        struct amdgpu_job *job;
 744        struct amdgpu_ib *ib;
 745        struct dma_fence *f = NULL;
 746        const unsigned ib_size_dw = 16;
 747        int i, r;
 748
 749        r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job);
 750        if (r)
 751                return r;
 752
 753        ib = &job->ibs[0];
 754
 755        ib->ptr[0] = PACKETJ(adev->vcn.internal.jpeg_pitch, 0, 0, PACKETJ_TYPE0);
 756        ib->ptr[1] = 0xDEADBEEF;
 757        for (i = 2; i < 16; i += 2) {
 758                ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
 759                ib->ptr[i+1] = 0;
 760        }
 761        ib->length_dw = 16;
 762
 763        r = amdgpu_job_submit_direct(job, ring, &f);
 764        if (r)
 765                goto err;
 766
 767        if (fence)
 768                *fence = dma_fence_get(f);
 769        dma_fence_put(f);
 770
 771        return 0;
 772
 773err:
 774        amdgpu_job_free(job);
 775        return r;
 776}
 777
 778int amdgpu_vcn_jpeg_ring_test_ib(struct amdgpu_ring *ring, long timeout)
 779{
 780        struct amdgpu_device *adev = ring->adev;
 781        uint32_t tmp = 0;
 782        unsigned i;
 783        struct dma_fence *fence = NULL;
 784        long r = 0;
 785
 786        r = amdgpu_vcn_jpeg_set_reg(ring, 1, &fence);
 787        if (r)
 788                goto error;
 789
 790        r = dma_fence_wait_timeout(fence, false, timeout);
 791        if (r == 0) {
 792                r = -ETIMEDOUT;
 793                goto error;
 794        } else if (r < 0) {
 795                goto error;
 796        } else {
 797                r = 0;
 798        }
 799
 800        for (i = 0; i < adev->usec_timeout; i++) {
 801                tmp = RREG32(adev->vcn.inst[ring->me].external.jpeg_pitch);
 802                if (tmp == 0xDEADBEEF)
 803                        break;
 804                udelay(1);
 805        }
 806
 807        if (i >= adev->usec_timeout)
 808                r = -ETIMEDOUT;
 809
 810        dma_fence_put(fence);
 811error:
 812        return r;
 813}
 814