Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2021 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 #include <linux/firmware.h>
0025 #include "amdgpu.h"
0026 #include "amdgpu_vcn.h"
0027 #include "amdgpu_pm.h"
0028 #include "amdgpu_cs.h"
0029 #include "soc15.h"
0030 #include "soc15d.h"
0031 #include "soc15_hw_ip.h"
0032 #include "vcn_v2_0.h"
0033 
0034 #include "vcn/vcn_4_0_0_offset.h"
0035 #include "vcn/vcn_4_0_0_sh_mask.h"
0036 #include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"
0037 
0038 #include <drm/drm_drv.h>
0039 
0040 #define mmUVD_DPG_LMA_CTL                           regUVD_DPG_LMA_CTL
0041 #define mmUVD_DPG_LMA_CTL_BASE_IDX                      regUVD_DPG_LMA_CTL_BASE_IDX
0042 #define mmUVD_DPG_LMA_DATA                          regUVD_DPG_LMA_DATA
0043 #define mmUVD_DPG_LMA_DATA_BASE_IDX                     regUVD_DPG_LMA_DATA_BASE_IDX
0044 
0045 #define VCN_VID_SOC_ADDRESS_2_0                         0x1fb00
0046 #define VCN1_VID_SOC_ADDRESS_3_0                        0x48300
0047 
0048 #define RDECODE_MSG_CREATE                          0x00000000
0049 #define RDECODE_MESSAGE_CREATE                          0x00000001
0050 
0051 static int amdgpu_ih_clientid_vcns[] = {
0052     SOC15_IH_CLIENTID_VCN,
0053     SOC15_IH_CLIENTID_VCN1
0054 };
0055 
0056 static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev);
0057 static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev);
0058 static int vcn_v4_0_set_powergating_state(void *handle,
0059         enum amd_powergating_state state);
0060 static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev,
0061         int inst_idx, struct dpg_pause_state *new_state);
0062 
0063 /**
0064  * vcn_v4_0_early_init - set function pointers
0065  *
0066  * @handle: amdgpu_device pointer
0067  *
0068  * Set ring and irq function pointers
0069  */
0070 static int vcn_v4_0_early_init(void *handle)
0071 {
0072     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0073 
0074     /* re-use enc ring as unified ring */
0075     adev->vcn.num_enc_rings = 1;
0076 
0077     vcn_v4_0_set_unified_ring_funcs(adev);
0078     vcn_v4_0_set_irq_funcs(adev);
0079 
0080     return 0;
0081 }
0082 
0083 /**
0084  * vcn_v4_0_sw_init - sw init for VCN block
0085  *
0086  * @handle: amdgpu_device pointer
0087  *
0088  * Load firmware and sw initialization
0089  */
0090 static int vcn_v4_0_sw_init(void *handle)
0091 {
0092     struct amdgpu_ring *ring;
0093     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0094     int i, r;
0095 
0096     r = amdgpu_vcn_sw_init(adev);
0097     if (r)
0098         return r;
0099 
0100     amdgpu_vcn_setup_ucode(adev);
0101 
0102     r = amdgpu_vcn_resume(adev);
0103     if (r)
0104         return r;
0105 
0106     for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
0107         volatile struct amdgpu_vcn4_fw_shared *fw_shared;
0108 
0109         if (adev->vcn.harvest_config & (1 << i))
0110             continue;
0111 
0112         atomic_set(&adev->vcn.inst[i].sched_score, 0);
0113 
0114         /* VCN UNIFIED TRAP */
0115         r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],
0116                 VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq);
0117         if (r)
0118             return r;
0119 
0120         ring = &adev->vcn.inst[i].ring_enc[0];
0121         ring->use_doorbell = true;
0122         ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + 8 * i;
0123 
0124         sprintf(ring->name, "vcn_unified_%d", i);
0125 
0126         r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,
0127                         AMDGPU_RING_PRIO_0, &adev->vcn.inst[i].sched_score);
0128         if (r)
0129             return r;
0130 
0131         fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
0132         fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
0133         fw_shared->sq.is_enabled = 1;
0134 
0135         if (amdgpu_vcnfw_log)
0136             amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
0137     }
0138 
0139     if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
0140         adev->vcn.pause_dpg_mode = vcn_v4_0_pause_dpg_mode;
0141 
0142     return 0;
0143 }
0144 
0145 /**
0146  * vcn_v4_0_sw_fini - sw fini for VCN block
0147  *
0148  * @handle: amdgpu_device pointer
0149  *
0150  * VCN suspend and free up sw allocation
0151  */
0152 static int vcn_v4_0_sw_fini(void *handle)
0153 {
0154     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0155     int i, r, idx;
0156 
0157     if (drm_dev_enter(adev_to_drm(adev), &idx)) {
0158         for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
0159             volatile struct amdgpu_vcn4_fw_shared *fw_shared;
0160 
0161             if (adev->vcn.harvest_config & (1 << i))
0162                 continue;
0163 
0164             fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
0165             fw_shared->present_flag_0 = 0;
0166             fw_shared->sq.is_enabled = 0;
0167         }
0168 
0169         drm_dev_exit(idx);
0170     }
0171 
0172     r = amdgpu_vcn_suspend(adev);
0173     if (r)
0174         return r;
0175 
0176     r = amdgpu_vcn_sw_fini(adev);
0177 
0178     return r;
0179 }
0180 
0181 /**
0182  * vcn_v4_0_hw_init - start and test VCN block
0183  *
0184  * @handle: amdgpu_device pointer
0185  *
0186  * Initialize the hardware, boot up the VCPU and do some testing
0187  */
0188 static int vcn_v4_0_hw_init(void *handle)
0189 {
0190     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0191     struct amdgpu_ring *ring;
0192     int i, r;
0193 
0194     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
0195         if (adev->vcn.harvest_config & (1 << i))
0196             continue;
0197 
0198         ring = &adev->vcn.inst[i].ring_enc[0];
0199 
0200         adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,
0201                 ((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i), i);
0202 
0203         r = amdgpu_ring_test_helper(ring);
0204         if (r)
0205             goto done;
0206     }
0207 
0208 done:
0209     if (!r)
0210         DRM_INFO("VCN decode and encode initialized successfully(under %s).\n",
0211             (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)?"DPG Mode":"SPG Mode");
0212 
0213     return r;
0214 }
0215 
0216 /**
0217  * vcn_v4_0_hw_fini - stop the hardware block
0218  *
0219  * @handle: amdgpu_device pointer
0220  *
0221  * Stop the VCN block, mark ring as not ready any more
0222  */
0223 static int vcn_v4_0_hw_fini(void *handle)
0224 {
0225     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0226     int i;
0227 
0228     cancel_delayed_work_sync(&adev->vcn.idle_work);
0229 
0230     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
0231         if (adev->vcn.harvest_config & (1 << i))
0232             continue;
0233 
0234         if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
0235                         (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
0236                                 RREG32_SOC15(VCN, i, regUVD_STATUS))) {
0237                         vcn_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
0238         }
0239     }
0240 
0241     return 0;
0242 }
0243 
0244 /**
0245  * vcn_v4_0_suspend - suspend VCN block
0246  *
0247  * @handle: amdgpu_device pointer
0248  *
0249  * HW fini and suspend VCN block
0250  */
0251 static int vcn_v4_0_suspend(void *handle)
0252 {
0253     int r;
0254     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0255 
0256     r = vcn_v4_0_hw_fini(adev);
0257     if (r)
0258         return r;
0259 
0260     r = amdgpu_vcn_suspend(adev);
0261 
0262     return r;
0263 }
0264 
0265 /**
0266  * vcn_v4_0_resume - resume VCN block
0267  *
0268  * @handle: amdgpu_device pointer
0269  *
0270  * Resume firmware and hw init VCN block
0271  */
0272 static int vcn_v4_0_resume(void *handle)
0273 {
0274     int r;
0275     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
0276 
0277     r = amdgpu_vcn_resume(adev);
0278     if (r)
0279         return r;
0280 
0281     r = vcn_v4_0_hw_init(adev);
0282 
0283     return r;
0284 }
0285 
0286 /**
0287  * vcn_v4_0_mc_resume - memory controller programming
0288  *
0289  * @adev: amdgpu_device pointer
0290  * @inst: instance number
0291  *
0292  * Let the VCN memory controller know it's offsets
0293  */
0294 static void vcn_v4_0_mc_resume(struct amdgpu_device *adev, int inst)
0295 {
0296     uint32_t offset, size;
0297     const struct common_firmware_header *hdr;
0298 
0299     hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
0300     size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
0301 
0302     /* cache window 0: fw */
0303     if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
0304         WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
0305             (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo));
0306         WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
0307             (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi));
0308         WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, 0);
0309         offset = 0;
0310     } else {
0311         WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
0312             lower_32_bits(adev->vcn.inst[inst].gpu_addr));
0313         WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,
0314             upper_32_bits(adev->vcn.inst[inst].gpu_addr));
0315         offset = size;
0316                 WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
0317     }
0318     WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE0, size);
0319 
0320     /* cache window 1: stack */
0321     WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
0322         lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
0323     WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
0324         upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset));
0325     WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET1, 0);
0326     WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
0327 
0328     /* cache window 2: context */
0329     WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
0330         lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
0331     WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
0332         upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
0333     WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET2, 0);
0334     WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
0335 
0336     /* non-cache window */
0337     WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,
0338         lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
0339     WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,
0340         upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));
0341     WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);
0342     WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0,
0343         AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)));
0344 }
0345 
0346 /**
0347  * vcn_v4_0_mc_resume_dpg_mode - memory controller programming for dpg mode
0348  *
0349  * @adev: amdgpu_device pointer
0350  * @inst_idx: instance number index
0351  * @indirect: indirectly write sram
0352  *
0353  * Let the VCN memory controller know it's offsets with dpg mode
0354  */
0355 static void vcn_v4_0_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
0356 {
0357     uint32_t offset, size;
0358     const struct common_firmware_header *hdr;
0359     hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
0360     size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
0361 
0362     /* cache window 0: fw */
0363     if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
0364         if (!indirect) {
0365             WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0366                 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
0367                 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_lo), 0, indirect);
0368             WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0369                 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
0370                 (adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_hi), 0, indirect);
0371             WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0372                 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
0373         } else {
0374             WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0375                 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);
0376             WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0377                 VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);
0378             WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0379                 VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);
0380         }
0381         offset = 0;
0382     } else {
0383         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0384             VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
0385             lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
0386         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0387             VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
0388             upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);
0389         offset = size;
0390         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0391             VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0),
0392             AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);
0393     }
0394 
0395     if (!indirect)
0396         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0397             VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);
0398     else
0399         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0400             VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);
0401 
0402     /* cache window 1: stack */
0403     if (!indirect) {
0404         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0405             VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
0406             lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
0407         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0408             VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),
0409             upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);
0410         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0411             VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
0412     } else {
0413         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0414             VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);
0415         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0416             VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);
0417         WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0418             VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);
0419     }
0420     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0421             VCN, inst_idx, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);
0422 
0423     /* cache window 2: context */
0424     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0425             VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),
0426             lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect);
0427     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0428             VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),
0429             upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE), 0, indirect);
0430     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0431             VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);
0432     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0433             VCN, inst_idx, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);
0434 
0435     /* non-cache window */
0436     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0437             VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),
0438             lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
0439     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0440             VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),
0441             upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);
0442     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0443             VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);
0444     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0445             VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0),
0446             AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect);
0447 
0448     /* VCN global tiling registers */
0449     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0450         VCN, 0, regUVD_GFX10_ADDR_CONFIG), adev->gfx.config.gb_addr_config, 0, indirect);
0451 }
0452 
0453 /**
0454  * vcn_v4_0_disable_static_power_gating - disable VCN static power gating
0455  *
0456  * @adev: amdgpu_device pointer
0457  * @inst: instance number
0458  *
0459  * Disable static power gating for VCN block
0460  */
0461 static void vcn_v4_0_disable_static_power_gating(struct amdgpu_device *adev, int inst)
0462 {
0463     uint32_t data = 0;
0464 
0465     if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
0466         data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
0467             | 1 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT
0468             | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT
0469             | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
0470             | 2 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT
0471             | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
0472             | 2 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT
0473             | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
0474             | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
0475             | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
0476             | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT
0477             | 2 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT
0478             | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT
0479             | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT);
0480 
0481         WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data);
0482         SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS,
0483             UVD_PGFSM_STATUS__UVDM_UVDU_UVDLM_PWR_ON_3_0, 0x3F3FFFFF);
0484     } else {
0485         uint32_t value;
0486 
0487         value = (inst) ? 0x2200800 : 0;
0488         data = (1 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
0489             | 1 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT
0490             | 1 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT
0491             | 1 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
0492             | 1 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT
0493             | 1 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
0494             | 1 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT
0495             | 1 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
0496             | 1 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
0497             | 1 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
0498             | 1 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT
0499             | 1 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT
0500             | 1 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT
0501             | 1 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT);
0502 
0503                 WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data);
0504                 SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, value,  0x3F3FFFFF);
0505         }
0506 
0507         data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);
0508         data &= ~0x103;
0509         if (adev->pg_flags & AMD_PG_SUPPORT_VCN)
0510                 data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON |
0511                         UVD_POWER_STATUS__UVD_PG_EN_MASK;
0512 
0513         WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);
0514 
0515         return;
0516 }
0517 
0518 /**
0519  * vcn_v4_0_enable_static_power_gating - enable VCN static power gating
0520  *
0521  * @adev: amdgpu_device pointer
0522  * @inst: instance number
0523  *
0524  * Enable static power gating for VCN block
0525  */
0526 static void vcn_v4_0_enable_static_power_gating(struct amdgpu_device *adev, int inst)
0527 {
0528     uint32_t data;
0529 
0530     if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {
0531         /* Before power off, this indicator has to be turned on */
0532         data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);
0533         data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;
0534         data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;
0535         WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);
0536 
0537         data = (2 << UVD_PGFSM_CONFIG__UVDM_PWR_CONFIG__SHIFT
0538             | 2 << UVD_PGFSM_CONFIG__UVDS_PWR_CONFIG__SHIFT
0539             | 2 << UVD_PGFSM_CONFIG__UVDF_PWR_CONFIG__SHIFT
0540             | 2 << UVD_PGFSM_CONFIG__UVDTC_PWR_CONFIG__SHIFT
0541             | 2 << UVD_PGFSM_CONFIG__UVDB_PWR_CONFIG__SHIFT
0542             | 2 << UVD_PGFSM_CONFIG__UVDTA_PWR_CONFIG__SHIFT
0543             | 2 << UVD_PGFSM_CONFIG__UVDLM_PWR_CONFIG__SHIFT
0544             | 2 << UVD_PGFSM_CONFIG__UVDTD_PWR_CONFIG__SHIFT
0545             | 2 << UVD_PGFSM_CONFIG__UVDTE_PWR_CONFIG__SHIFT
0546             | 2 << UVD_PGFSM_CONFIG__UVDE_PWR_CONFIG__SHIFT
0547             | 2 << UVD_PGFSM_CONFIG__UVDAB_PWR_CONFIG__SHIFT
0548             | 2 << UVD_PGFSM_CONFIG__UVDTB_PWR_CONFIG__SHIFT
0549             | 2 << UVD_PGFSM_CONFIG__UVDNA_PWR_CONFIG__SHIFT
0550             | 2 << UVD_PGFSM_CONFIG__UVDNB_PWR_CONFIG__SHIFT);
0551         WREG32_SOC15(VCN, inst, regUVD_PGFSM_CONFIG, data);
0552 
0553         data = (2 << UVD_PGFSM_STATUS__UVDM_PWR_STATUS__SHIFT
0554             | 2 << UVD_PGFSM_STATUS__UVDS_PWR_STATUS__SHIFT
0555             | 2 << UVD_PGFSM_STATUS__UVDF_PWR_STATUS__SHIFT
0556             | 2 << UVD_PGFSM_STATUS__UVDTC_PWR_STATUS__SHIFT
0557             | 2 << UVD_PGFSM_STATUS__UVDB_PWR_STATUS__SHIFT
0558             | 2 << UVD_PGFSM_STATUS__UVDTA_PWR_STATUS__SHIFT
0559             | 2 << UVD_PGFSM_STATUS__UVDLM_PWR_STATUS__SHIFT
0560             | 2 << UVD_PGFSM_STATUS__UVDTD_PWR_STATUS__SHIFT
0561             | 2 << UVD_PGFSM_STATUS__UVDTE_PWR_STATUS__SHIFT
0562             | 2 << UVD_PGFSM_STATUS__UVDE_PWR_STATUS__SHIFT
0563             | 2 << UVD_PGFSM_STATUS__UVDAB_PWR_STATUS__SHIFT
0564             | 2 << UVD_PGFSM_STATUS__UVDTB_PWR_STATUS__SHIFT
0565             | 2 << UVD_PGFSM_STATUS__UVDNA_PWR_STATUS__SHIFT
0566             | 2 << UVD_PGFSM_STATUS__UVDNB_PWR_STATUS__SHIFT);
0567         SOC15_WAIT_ON_RREG(VCN, inst, regUVD_PGFSM_STATUS, data, 0x3F3FFFFF);
0568     }
0569 
0570         return;
0571 }
0572 
0573 /**
0574  * vcn_v4_0_disable_clock_gating - disable VCN clock gating
0575  *
0576  * @adev: amdgpu_device pointer
0577  * @inst: instance number
0578  *
0579  * Disable clock gating for VCN block
0580  */
0581 static void vcn_v4_0_disable_clock_gating(struct amdgpu_device *adev, int inst)
0582 {
0583     uint32_t data;
0584 
0585     if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
0586         return;
0587 
0588     /* VCN disable CGC */
0589     data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
0590     data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;
0591     data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
0592     data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
0593     WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
0594 
0595     data = RREG32_SOC15(VCN, inst, regUVD_CGC_GATE);
0596     data &= ~(UVD_CGC_GATE__SYS_MASK
0597         | UVD_CGC_GATE__UDEC_MASK
0598         | UVD_CGC_GATE__MPEG2_MASK
0599         | UVD_CGC_GATE__REGS_MASK
0600         | UVD_CGC_GATE__RBC_MASK
0601         | UVD_CGC_GATE__LMI_MC_MASK
0602         | UVD_CGC_GATE__LMI_UMC_MASK
0603         | UVD_CGC_GATE__IDCT_MASK
0604         | UVD_CGC_GATE__MPRD_MASK
0605         | UVD_CGC_GATE__MPC_MASK
0606         | UVD_CGC_GATE__LBSI_MASK
0607         | UVD_CGC_GATE__LRBBM_MASK
0608         | UVD_CGC_GATE__UDEC_RE_MASK
0609         | UVD_CGC_GATE__UDEC_CM_MASK
0610         | UVD_CGC_GATE__UDEC_IT_MASK
0611         | UVD_CGC_GATE__UDEC_DB_MASK
0612         | UVD_CGC_GATE__UDEC_MP_MASK
0613         | UVD_CGC_GATE__WCB_MASK
0614         | UVD_CGC_GATE__VCPU_MASK
0615         | UVD_CGC_GATE__MMSCH_MASK);
0616 
0617     WREG32_SOC15(VCN, inst, regUVD_CGC_GATE, data);
0618     SOC15_WAIT_ON_RREG(VCN, inst, regUVD_CGC_GATE, 0,  0xFFFFFFFF);
0619 
0620     data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
0621     data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK
0622         | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
0623         | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
0624         | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
0625         | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
0626         | UVD_CGC_CTRL__SYS_MODE_MASK
0627         | UVD_CGC_CTRL__UDEC_MODE_MASK
0628         | UVD_CGC_CTRL__MPEG2_MODE_MASK
0629         | UVD_CGC_CTRL__REGS_MODE_MASK
0630         | UVD_CGC_CTRL__RBC_MODE_MASK
0631         | UVD_CGC_CTRL__LMI_MC_MODE_MASK
0632         | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
0633         | UVD_CGC_CTRL__IDCT_MODE_MASK
0634         | UVD_CGC_CTRL__MPRD_MODE_MASK
0635         | UVD_CGC_CTRL__MPC_MODE_MASK
0636         | UVD_CGC_CTRL__LBSI_MODE_MASK
0637         | UVD_CGC_CTRL__LRBBM_MODE_MASK
0638         | UVD_CGC_CTRL__WCB_MODE_MASK
0639         | UVD_CGC_CTRL__VCPU_MODE_MASK
0640         | UVD_CGC_CTRL__MMSCH_MODE_MASK);
0641     WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
0642 
0643     data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE);
0644     data |= (UVD_SUVD_CGC_GATE__SRE_MASK
0645         | UVD_SUVD_CGC_GATE__SIT_MASK
0646         | UVD_SUVD_CGC_GATE__SMP_MASK
0647         | UVD_SUVD_CGC_GATE__SCM_MASK
0648         | UVD_SUVD_CGC_GATE__SDB_MASK
0649         | UVD_SUVD_CGC_GATE__SRE_H264_MASK
0650         | UVD_SUVD_CGC_GATE__SRE_HEVC_MASK
0651         | UVD_SUVD_CGC_GATE__SIT_H264_MASK
0652         | UVD_SUVD_CGC_GATE__SIT_HEVC_MASK
0653         | UVD_SUVD_CGC_GATE__SCM_H264_MASK
0654         | UVD_SUVD_CGC_GATE__SCM_HEVC_MASK
0655         | UVD_SUVD_CGC_GATE__SDB_H264_MASK
0656         | UVD_SUVD_CGC_GATE__SDB_HEVC_MASK
0657         | UVD_SUVD_CGC_GATE__SCLR_MASK
0658         | UVD_SUVD_CGC_GATE__UVD_SC_MASK
0659         | UVD_SUVD_CGC_GATE__ENT_MASK
0660         | UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK
0661         | UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK
0662         | UVD_SUVD_CGC_GATE__SITE_MASK
0663         | UVD_SUVD_CGC_GATE__SRE_VP9_MASK
0664         | UVD_SUVD_CGC_GATE__SCM_VP9_MASK
0665         | UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK
0666         | UVD_SUVD_CGC_GATE__SDB_VP9_MASK
0667         | UVD_SUVD_CGC_GATE__IME_HEVC_MASK);
0668     WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE, data);
0669 
0670     data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL);
0671     data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
0672         | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
0673         | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
0674         | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
0675         | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
0676         | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
0677         | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
0678         | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
0679         | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
0680         | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
0681     WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
0682 }
0683 
0684 /**
0685  * vcn_v4_0_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode
0686  *
0687  * @adev: amdgpu_device pointer
0688  * @sram_sel: sram select
0689  * @inst_idx: instance number index
0690  * @indirect: indirectly write sram
0691  *
0692  * Disable clock gating for VCN block with dpg mode
0693  */
0694 static void vcn_v4_0_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,
0695       int inst_idx, uint8_t indirect)
0696 {
0697     uint32_t reg_data = 0;
0698 
0699     if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
0700         return;
0701 
0702     /* enable sw clock gating control */
0703     reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
0704     reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
0705     reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
0706     reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
0707          UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
0708          UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
0709          UVD_CGC_CTRL__UDEC_DB_MODE_MASK |
0710          UVD_CGC_CTRL__UDEC_MP_MODE_MASK |
0711          UVD_CGC_CTRL__SYS_MODE_MASK |
0712          UVD_CGC_CTRL__UDEC_MODE_MASK |
0713          UVD_CGC_CTRL__MPEG2_MODE_MASK |
0714          UVD_CGC_CTRL__REGS_MODE_MASK |
0715          UVD_CGC_CTRL__RBC_MODE_MASK |
0716          UVD_CGC_CTRL__LMI_MC_MODE_MASK |
0717          UVD_CGC_CTRL__LMI_UMC_MODE_MASK |
0718          UVD_CGC_CTRL__IDCT_MODE_MASK |
0719          UVD_CGC_CTRL__MPRD_MODE_MASK |
0720          UVD_CGC_CTRL__MPC_MODE_MASK |
0721          UVD_CGC_CTRL__LBSI_MODE_MASK |
0722          UVD_CGC_CTRL__LRBBM_MODE_MASK |
0723          UVD_CGC_CTRL__WCB_MODE_MASK |
0724          UVD_CGC_CTRL__VCPU_MODE_MASK);
0725     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0726         VCN, inst_idx, regUVD_CGC_CTRL), reg_data, sram_sel, indirect);
0727 
0728     /* turn off clock gating */
0729     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0730         VCN, inst_idx, regUVD_CGC_GATE), 0, sram_sel, indirect);
0731 
0732     /* turn on SUVD clock gating */
0733     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0734         VCN, inst_idx, regUVD_SUVD_CGC_GATE), 1, sram_sel, indirect);
0735 
0736     /* turn on sw mode in UVD_SUVD_CGC_CTRL */
0737     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0738         VCN, inst_idx, regUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect);
0739 }
0740 
0741 /**
0742  * vcn_v4_0_enable_clock_gating - enable VCN clock gating
0743  *
0744  * @adev: amdgpu_device pointer
0745  * @inst: instance number
0746  *
0747  * Enable clock gating for VCN block
0748  */
0749 static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
0750 {
0751     uint32_t data;
0752 
0753     if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)
0754         return;
0755 
0756     /* enable VCN CGC */
0757     data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
0758     data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
0759     data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
0760     data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
0761     WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
0762 
0763     data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);
0764     data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK
0765         | UVD_CGC_CTRL__UDEC_CM_MODE_MASK
0766         | UVD_CGC_CTRL__UDEC_IT_MODE_MASK
0767         | UVD_CGC_CTRL__UDEC_DB_MODE_MASK
0768         | UVD_CGC_CTRL__UDEC_MP_MODE_MASK
0769         | UVD_CGC_CTRL__SYS_MODE_MASK
0770         | UVD_CGC_CTRL__UDEC_MODE_MASK
0771         | UVD_CGC_CTRL__MPEG2_MODE_MASK
0772         | UVD_CGC_CTRL__REGS_MODE_MASK
0773         | UVD_CGC_CTRL__RBC_MODE_MASK
0774         | UVD_CGC_CTRL__LMI_MC_MODE_MASK
0775         | UVD_CGC_CTRL__LMI_UMC_MODE_MASK
0776         | UVD_CGC_CTRL__IDCT_MODE_MASK
0777         | UVD_CGC_CTRL__MPRD_MODE_MASK
0778         | UVD_CGC_CTRL__MPC_MODE_MASK
0779         | UVD_CGC_CTRL__LBSI_MODE_MASK
0780         | UVD_CGC_CTRL__LRBBM_MODE_MASK
0781         | UVD_CGC_CTRL__WCB_MODE_MASK
0782         | UVD_CGC_CTRL__VCPU_MODE_MASK
0783         | UVD_CGC_CTRL__MMSCH_MODE_MASK);
0784     WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);
0785 
0786     data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL);
0787     data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK
0788         | UVD_SUVD_CGC_CTRL__SIT_MODE_MASK
0789         | UVD_SUVD_CGC_CTRL__SMP_MODE_MASK
0790         | UVD_SUVD_CGC_CTRL__SCM_MODE_MASK
0791         | UVD_SUVD_CGC_CTRL__SDB_MODE_MASK
0792         | UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK
0793         | UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK
0794         | UVD_SUVD_CGC_CTRL__ENT_MODE_MASK
0795         | UVD_SUVD_CGC_CTRL__IME_MODE_MASK
0796         | UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);
0797     WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);
0798 
0799     return;
0800 }
0801 
0802 /**
0803  * vcn_v4_0_start_dpg_mode - VCN start with dpg mode
0804  *
0805  * @adev: amdgpu_device pointer
0806  * @inst_idx: instance number index
0807  * @indirect: indirectly write sram
0808  *
0809  * Start VCN block with dpg mode
0810  */
0811 static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
0812 {
0813     volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
0814     struct amdgpu_ring *ring;
0815     uint32_t tmp;
0816 
0817     /* disable register anti-hang mechanism */
0818     WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 1,
0819         ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
0820     /* enable dynamic power gating mode */
0821     tmp = RREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS);
0822     tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;
0823     tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK;
0824     WREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS, tmp);
0825 
0826     if (indirect)
0827         adev->vcn.inst[inst_idx].dpg_sram_curr_addr = (uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;
0828 
0829     /* enable clock gating */
0830     vcn_v4_0_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);
0831 
0832     /* enable VCPU clock */
0833     tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
0834     tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK;
0835     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0836         VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);
0837 
0838     /* disable master interupt */
0839     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0840         VCN, inst_idx, regUVD_MASTINT_EN), 0, 0, indirect);
0841 
0842     /* setup regUVD_LMI_CTRL */
0843     tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
0844         UVD_LMI_CTRL__REQ_MODE_MASK |
0845         UVD_LMI_CTRL__CRC_RESET_MASK |
0846         UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
0847         UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
0848         UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
0849         (8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
0850         0x00100000L);
0851     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0852         VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect);
0853 
0854     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0855         VCN, inst_idx, regUVD_MPC_CNTL),
0856         0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0, indirect);
0857 
0858     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0859         VCN, inst_idx, regUVD_MPC_SET_MUXA0),
0860         ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
0861          (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
0862          (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
0863          (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0, indirect);
0864 
0865     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0866         VCN, inst_idx, regUVD_MPC_SET_MUXB0),
0867          ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
0868          (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
0869          (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
0870          (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0, indirect);
0871 
0872     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0873         VCN, inst_idx, regUVD_MPC_SET_MUX),
0874         ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
0875          (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
0876          (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);
0877 
0878     vcn_v4_0_mc_resume_dpg_mode(adev, inst_idx, indirect);
0879 
0880     tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);
0881     tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;
0882     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0883         VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);
0884 
0885     /* enable LMI MC and UMC channels */
0886     tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;
0887     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0888         VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);
0889 
0890     /* enable master interrupt */
0891     WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
0892         VCN, inst_idx, regUVD_MASTINT_EN),
0893         UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);
0894 
0895 
0896     if (indirect)
0897         psp_update_vcn_sram(adev, inst_idx, adev->vcn.inst[inst_idx].dpg_sram_gpu_addr,
0898             (uint32_t)((uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_curr_addr -
0899                 (uintptr_t)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr));
0900 
0901     ring = &adev->vcn.inst[inst_idx].ring_enc[0];
0902 
0903     WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_LO, ring->gpu_addr);
0904     WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
0905     WREG32_SOC15(VCN, inst_idx, regUVD_RB_SIZE, ring->ring_size / 4);
0906 
0907     tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);
0908     tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
0909     WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);
0910     fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
0911     WREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR, 0);
0912     WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, 0);
0913 
0914     tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR);
0915     WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, tmp);
0916     ring->wptr = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);
0917 
0918     tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);
0919     tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
0920     WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);
0921     fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
0922 
0923     WREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL,
0924             ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
0925             VCN_RB1_DB_CTRL__EN_MASK);
0926 
0927     return 0;
0928 }
0929 
0930 
0931 /**
0932  * vcn_v4_0_start - VCN start
0933  *
0934  * @adev: amdgpu_device pointer
0935  *
0936  * Start VCN block
0937  */
0938 static int vcn_v4_0_start(struct amdgpu_device *adev)
0939 {
0940     volatile struct amdgpu_vcn4_fw_shared *fw_shared;
0941     struct amdgpu_ring *ring;
0942     uint32_t tmp;
0943     int i, j, k, r;
0944 
0945     if (adev->pm.dpm_enabled)
0946         amdgpu_dpm_enable_uvd(adev, true);
0947 
0948     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
0949         fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
0950 
0951         if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
0952             r = vcn_v4_0_start_dpg_mode(adev, i, adev->vcn.indirect_sram);
0953             continue;
0954         }
0955 
0956         /* disable VCN power gating */
0957         vcn_v4_0_disable_static_power_gating(adev, i);
0958 
0959         /* set VCN status busy */
0960         tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;
0961         WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);
0962 
0963         /*SW clock gating */
0964         vcn_v4_0_disable_clock_gating(adev, i);
0965 
0966         /* enable VCPU clock */
0967         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
0968                 UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);
0969 
0970         /* disable master interrupt */
0971         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,
0972                 ~UVD_MASTINT_EN__VCPU_EN_MASK);
0973 
0974         /* enable LMI MC and UMC channels */
0975         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,
0976                 ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
0977 
0978         tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
0979         tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
0980         tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
0981         WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
0982 
0983         /* setup regUVD_LMI_CTRL */
0984         tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);
0985         WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |
0986                 UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
0987                 UVD_LMI_CTRL__MASK_MC_URGENT_MASK |
0988                 UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
0989                 UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);
0990 
0991         /* setup regUVD_MPC_CNTL */
0992         tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);
0993         tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;
0994         tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;
0995         WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);
0996 
0997         /* setup UVD_MPC_SET_MUXA0 */
0998         WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,
0999                 ((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |
1000                  (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |
1001                  (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |
1002                  (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));
1003 
1004         /* setup UVD_MPC_SET_MUXB0 */
1005         WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,
1006                 ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |
1007                  (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |
1008                  (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |
1009                  (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));
1010 
1011         /* setup UVD_MPC_SET_MUX */
1012         WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,
1013                 ((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |
1014                  (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |
1015                  (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));
1016 
1017         vcn_v4_0_mc_resume(adev, i);
1018 
1019         /* VCN global tiling registers */
1020         WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,
1021                 adev->gfx.config.gb_addr_config);
1022 
1023         /* unblock VCPU register access */
1024         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,
1025                 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
1026 
1027         /* release VCPU reset to boot */
1028         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
1029                 ~UVD_VCPU_CNTL__BLK_RST_MASK);
1030 
1031         for (j = 0; j < 10; ++j) {
1032             uint32_t status;
1033 
1034             for (k = 0; k < 100; ++k) {
1035                 status = RREG32_SOC15(VCN, i, regUVD_STATUS);
1036                 if (status & 2)
1037                     break;
1038                 mdelay(10);
1039                 if (amdgpu_emu_mode==1)
1040                     msleep(1);
1041             }
1042 
1043             if (amdgpu_emu_mode==1) {
1044                 r = -1;
1045                 if (status & 2) {
1046                     r = 0;
1047                     break;
1048                 }
1049             } else {
1050                 r = 0;
1051                 if (status & 2)
1052                     break;
1053 
1054                 dev_err(adev->dev, "VCN[%d] is not responding, trying to reset the VCPU!!!\n", i);
1055                 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
1056                             UVD_VCPU_CNTL__BLK_RST_MASK,
1057                             ~UVD_VCPU_CNTL__BLK_RST_MASK);
1058                 mdelay(10);
1059                 WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
1060                         ~UVD_VCPU_CNTL__BLK_RST_MASK);
1061 
1062                 mdelay(10);
1063                 r = -1;
1064             }
1065         }
1066 
1067         if (r) {
1068             dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);
1069             return r;
1070         }
1071 
1072         /* enable master interrupt */
1073         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),
1074                 UVD_MASTINT_EN__VCPU_EN_MASK,
1075                 ~UVD_MASTINT_EN__VCPU_EN_MASK);
1076 
1077         /* clear the busy bit of VCN_STATUS */
1078         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,
1079                 ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));
1080 
1081         ring = &adev->vcn.inst[i].ring_enc[0];
1082         WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,
1083                 ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |
1084                 VCN_RB1_DB_CTRL__EN_MASK);
1085 
1086         WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);
1087         WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
1088         WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);
1089 
1090         tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
1091         tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);
1092         WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
1093         fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;
1094         WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);
1095         WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);
1096 
1097         tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);
1098         WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);
1099         ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);
1100 
1101         tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);
1102         tmp |= VCN_RB_ENABLE__RB1_EN_MASK;
1103         WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);
1104         fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);
1105     }
1106 
1107     return 0;
1108 }
1109 
1110 /**
1111  * vcn_v4_0_stop_dpg_mode - VCN stop with dpg mode
1112  *
1113  * @adev: amdgpu_device pointer
1114  * @inst_idx: instance number index
1115  *
1116  * Stop VCN block with dpg mode
1117  */
1118 static void vcn_v4_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)
1119 {
1120     uint32_t tmp;
1121 
1122     /* Wait for power status to be 1 */
1123     SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
1124         UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1125 
1126     /* wait for read ptr to be equal to write ptr */
1127     tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);
1128     SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);
1129 
1130     SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,
1131         UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1132 
1133     /* disable dynamic power gating mode */
1134     WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0,
1135         ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);
1136 }
1137 
1138 /**
1139  * vcn_v4_0_stop - VCN stop
1140  *
1141  * @adev: amdgpu_device pointer
1142  *
1143  * Stop VCN block
1144  */
1145 static int vcn_v4_0_stop(struct amdgpu_device *adev)
1146 {
1147     volatile struct amdgpu_vcn4_fw_shared *fw_shared;
1148     uint32_t tmp;
1149     int i, r = 0;
1150 
1151     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1152         fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
1153         fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;
1154 
1155         if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {
1156             vcn_v4_0_stop_dpg_mode(adev, i);
1157             continue;
1158         }
1159 
1160         /* wait for vcn idle */
1161         r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);
1162         if (r)
1163             return r;
1164 
1165         tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |
1166             UVD_LMI_STATUS__READ_CLEAN_MASK |
1167             UVD_LMI_STATUS__WRITE_CLEAN_MASK |
1168             UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;
1169         r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
1170         if (r)
1171             return r;
1172 
1173         /* disable LMI UMC channel */
1174         tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);
1175         tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;
1176         WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);
1177         tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |
1178             UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;
1179         r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);
1180         if (r)
1181             return r;
1182 
1183         /* block VCPU register access */
1184         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),
1185                 UVD_RB_ARB_CTRL__VCPU_DIS_MASK,
1186                 ~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);
1187 
1188         /* reset VCPU */
1189         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),
1190                 UVD_VCPU_CNTL__BLK_RST_MASK,
1191                 ~UVD_VCPU_CNTL__BLK_RST_MASK);
1192 
1193         /* disable VCPU clock */
1194         WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,
1195                 ~(UVD_VCPU_CNTL__CLK_EN_MASK));
1196 
1197         /* apply soft reset */
1198         tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
1199         tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;
1200         WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
1201         tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);
1202         tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;
1203         WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);
1204 
1205         /* clear status */
1206         WREG32_SOC15(VCN, i, regUVD_STATUS, 0);
1207 
1208         /* apply HW clock gating */
1209         vcn_v4_0_enable_clock_gating(adev, i);
1210 
1211         /* enable VCN power gating */
1212         vcn_v4_0_enable_static_power_gating(adev, i);
1213     }
1214 
1215     if (adev->pm.dpm_enabled)
1216         amdgpu_dpm_enable_uvd(adev, false);
1217 
1218     return 0;
1219 }
1220 
1221 /**
1222  * vcn_v4_0_pause_dpg_mode - VCN pause with dpg mode
1223  *
1224  * @adev: amdgpu_device pointer
1225  * @inst_idx: instance number index
1226  * @new_state: pause state
1227  *
1228  * Pause dpg mode for VCN block
1229  */
1230 static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,
1231       struct dpg_pause_state *new_state)
1232 {
1233     uint32_t reg_data = 0;
1234     int ret_code;
1235 
1236     /* pause/unpause if state is changed */
1237     if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {
1238         DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",
1239             adev->vcn.inst[inst_idx].pause_state.fw_based,  new_state->fw_based);
1240         reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &
1241             (~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
1242 
1243         if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {
1244             ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,
1245                 UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1246 
1247             if (!ret_code) {
1248                 /* pause DPG */
1249                 reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
1250                 WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
1251 
1252                 /* wait for ACK */
1253                 SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,
1254                     UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,
1255                     UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);
1256 
1257                 SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS,
1258                     UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON, UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);
1259             }
1260         } else {
1261             /* unpause dpg, no need to wait */
1262             reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;
1263             WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);
1264         }
1265         adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;
1266     }
1267 
1268     return 0;
1269 }
1270 
1271 /**
1272  * vcn_v4_0_unified_ring_get_rptr - get unified read pointer
1273  *
1274  * @ring: amdgpu_ring pointer
1275  *
1276  * Returns the current hardware unified read pointer
1277  */
1278 static uint64_t vcn_v4_0_unified_ring_get_rptr(struct amdgpu_ring *ring)
1279 {
1280     struct amdgpu_device *adev = ring->adev;
1281 
1282     if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
1283         DRM_ERROR("wrong ring id is identified in %s", __func__);
1284 
1285     return RREG32_SOC15(VCN, ring->me, regUVD_RB_RPTR);
1286 }
1287 
1288 /**
1289  * vcn_v4_0_unified_ring_get_wptr - get unified write pointer
1290  *
1291  * @ring: amdgpu_ring pointer
1292  *
1293  * Returns the current hardware unified write pointer
1294  */
1295 static uint64_t vcn_v4_0_unified_ring_get_wptr(struct amdgpu_ring *ring)
1296 {
1297     struct amdgpu_device *adev = ring->adev;
1298 
1299     if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
1300         DRM_ERROR("wrong ring id is identified in %s", __func__);
1301 
1302     if (ring->use_doorbell)
1303         return *ring->wptr_cpu_addr;
1304     else
1305         return RREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR);
1306 }
1307 
1308 /**
1309  * vcn_v4_0_unified_ring_set_wptr - set enc write pointer
1310  *
1311  * @ring: amdgpu_ring pointer
1312  *
1313  * Commits the enc write pointer to the hardware
1314  */
1315 static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring)
1316 {
1317     struct amdgpu_device *adev = ring->adev;
1318 
1319     if (ring != &adev->vcn.inst[ring->me].ring_enc[0])
1320         DRM_ERROR("wrong ring id is identified in %s", __func__);
1321 
1322     if (ring->use_doorbell) {
1323         *ring->wptr_cpu_addr = lower_32_bits(ring->wptr);
1324         WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
1325     } else {
1326         WREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR, lower_32_bits(ring->wptr));
1327     }
1328 }
1329 
1330 static int vcn_v4_0_limit_sched(struct amdgpu_cs_parser *p)
1331 {
1332     struct drm_gpu_scheduler **scheds;
1333 
1334     /* The create msg must be in the first IB submitted */
1335     if (atomic_read(&p->entity->fence_seq))
1336         return -EINVAL;
1337 
1338     scheds = p->adev->gpu_sched[AMDGPU_HW_IP_VCN_ENC]
1339         [AMDGPU_RING_PRIO_0].sched;
1340     drm_sched_entity_modify_sched(p->entity, scheds, 1);
1341     return 0;
1342 }
1343 
1344 static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, uint64_t addr)
1345 {
1346     struct ttm_operation_ctx ctx = { false, false };
1347     struct amdgpu_bo_va_mapping *map;
1348     uint32_t *msg, num_buffers;
1349     struct amdgpu_bo *bo;
1350     uint64_t start, end;
1351     unsigned int i;
1352     void *ptr;
1353     int r;
1354 
1355     addr &= AMDGPU_GMC_HOLE_MASK;
1356     r = amdgpu_cs_find_mapping(p, addr, &bo, &map);
1357     if (r) {
1358         DRM_ERROR("Can't find BO for addr 0x%08llx\n", addr);
1359         return r;
1360     }
1361 
1362     start = map->start * AMDGPU_GPU_PAGE_SIZE;
1363     end = (map->last + 1) * AMDGPU_GPU_PAGE_SIZE;
1364     if (addr & 0x7) {
1365         DRM_ERROR("VCN messages must be 8 byte aligned!\n");
1366         return -EINVAL;
1367     }
1368 
1369     bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
1370     amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
1371     r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
1372     if (r) {
1373         DRM_ERROR("Failed validating the VCN message BO (%d)!\n", r);
1374         return r;
1375     }
1376 
1377     r = amdgpu_bo_kmap(bo, &ptr);
1378     if (r) {
1379         DRM_ERROR("Failed mapping the VCN message (%d)!\n", r);
1380         return r;
1381     }
1382 
1383     msg = ptr + addr - start;
1384 
1385     /* Check length */
1386     if (msg[1] > end - addr) {
1387         r = -EINVAL;
1388         goto out;
1389     }
1390 
1391     if (msg[3] != RDECODE_MSG_CREATE)
1392         goto out;
1393 
1394     num_buffers = msg[2];
1395     for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) {
1396         uint32_t offset, size, *create;
1397 
1398         if (msg[0] != RDECODE_MESSAGE_CREATE)
1399             continue;
1400 
1401         offset = msg[1];
1402         size = msg[2];
1403 
1404         if (offset + size > end) {
1405             r = -EINVAL;
1406             goto out;
1407         }
1408 
1409         create = ptr + addr + offset - start;
1410 
1411         /* H246, HEVC and VP9 can run on any instance */
1412         if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11)
1413             continue;
1414 
1415         r = vcn_v4_0_limit_sched(p);
1416         if (r)
1417             goto out;
1418     }
1419 
1420 out:
1421     amdgpu_bo_kunmap(bo);
1422     return r;
1423 }
1424 
1425 #define RADEON_VCN_ENGINE_TYPE_DECODE                                 (0x00000003)
1426 
1427 static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
1428                 struct amdgpu_job *job,
1429                 struct amdgpu_ib *ib)
1430 {
1431     struct amdgpu_ring *ring = to_amdgpu_ring(p->entity->rq->sched);
1432     struct amdgpu_vcn_decode_buffer *decode_buffer = NULL;
1433     uint32_t val;
1434     int r = 0;
1435 
1436     /* The first instance can decode anything */
1437     if (!ring->me)
1438         return r;
1439 
1440     /* unified queue ib header has 8 double words. */
1441     if (ib->length_dw < 8)
1442         return r;
1443 
1444     val = amdgpu_ib_get_value(ib, 6); //RADEON_VCN_ENGINE_TYPE
1445 
1446     if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
1447         decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[10];
1448 
1449         if (decode_buffer->valid_buf_flag  & 0x1)
1450             r = vcn_v4_0_dec_msg(p, ((u64)decode_buffer->msg_buffer_address_hi) << 32 |
1451                         decode_buffer->msg_buffer_address_lo);
1452     }
1453     return r;
1454 }
1455 
1456 static const struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
1457     .type = AMDGPU_RING_TYPE_VCN_ENC,
1458     .align_mask = 0x3f,
1459     .nop = VCN_ENC_CMD_NO_OP,
1460     .vmhub = AMDGPU_MMHUB_0,
1461     .get_rptr = vcn_v4_0_unified_ring_get_rptr,
1462     .get_wptr = vcn_v4_0_unified_ring_get_wptr,
1463     .set_wptr = vcn_v4_0_unified_ring_set_wptr,
1464     .patch_cs_in_place = vcn_v4_0_ring_patch_cs_in_place,
1465     .emit_frame_size =
1466         SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +
1467         SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +
1468         4 + /* vcn_v2_0_enc_ring_emit_vm_flush */
1469         5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */
1470         1, /* vcn_v2_0_enc_ring_insert_end */
1471     .emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */
1472     .emit_ib = vcn_v2_0_enc_ring_emit_ib,
1473     .emit_fence = vcn_v2_0_enc_ring_emit_fence,
1474     .emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush,
1475     .test_ring = amdgpu_vcn_enc_ring_test_ring,
1476     .test_ib = amdgpu_vcn_unified_ring_test_ib,
1477     .insert_nop = amdgpu_ring_insert_nop,
1478     .insert_end = vcn_v2_0_enc_ring_insert_end,
1479     .pad_ib = amdgpu_ring_generic_pad_ib,
1480     .begin_use = amdgpu_vcn_ring_begin_use,
1481     .end_use = amdgpu_vcn_ring_end_use,
1482     .emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
1483     .emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
1484     .emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
1485 };
1486 
1487 /**
1488  * vcn_v4_0_set_unified_ring_funcs - set unified ring functions
1489  *
1490  * @adev: amdgpu_device pointer
1491  *
1492  * Set unified ring functions
1493  */
1494 static void vcn_v4_0_set_unified_ring_funcs(struct amdgpu_device *adev)
1495 {
1496     int i;
1497 
1498     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1499         if (adev->vcn.harvest_config & (1 << i))
1500             continue;
1501 
1502         adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_unified_ring_vm_funcs;
1503         adev->vcn.inst[i].ring_enc[0].me = i;
1504 
1505         DRM_INFO("VCN(%d) encode/decode are enabled in VM mode\n", i);
1506     }
1507 }
1508 
1509 /**
1510  * vcn_v4_0_is_idle - check VCN block is idle
1511  *
1512  * @handle: amdgpu_device pointer
1513  *
1514  * Check whether VCN block is idle
1515  */
1516 static bool vcn_v4_0_is_idle(void *handle)
1517 {
1518     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1519     int i, ret = 1;
1520 
1521     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1522         if (adev->vcn.harvest_config & (1 << i))
1523             continue;
1524 
1525         ret &= (RREG32_SOC15(VCN, i, regUVD_STATUS) == UVD_STATUS__IDLE);
1526     }
1527 
1528     return ret;
1529 }
1530 
1531 /**
1532  * vcn_v4_0_wait_for_idle - wait for VCN block idle
1533  *
1534  * @handle: amdgpu_device pointer
1535  *
1536  * Wait for VCN block idle
1537  */
1538 static int vcn_v4_0_wait_for_idle(void *handle)
1539 {
1540     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1541     int i, ret = 0;
1542 
1543     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1544         if (adev->vcn.harvest_config & (1 << i))
1545             continue;
1546 
1547         ret = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE,
1548             UVD_STATUS__IDLE);
1549         if (ret)
1550             return ret;
1551     }
1552 
1553     return ret;
1554 }
1555 
1556 /**
1557  * vcn_v4_0_set_clockgating_state - set VCN block clockgating state
1558  *
1559  * @handle: amdgpu_device pointer
1560  * @state: clock gating state
1561  *
1562  * Set VCN block clockgating state
1563  */
1564 static int vcn_v4_0_set_clockgating_state(void *handle, enum amd_clockgating_state state)
1565 {
1566     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1567     bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
1568     int i;
1569 
1570     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1571         if (adev->vcn.harvest_config & (1 << i))
1572             continue;
1573 
1574         if (enable) {
1575             if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)
1576                 return -EBUSY;
1577             vcn_v4_0_enable_clock_gating(adev, i);
1578         } else {
1579             vcn_v4_0_disable_clock_gating(adev, i);
1580         }
1581     }
1582 
1583     return 0;
1584 }
1585 
1586 /**
1587  * vcn_v4_0_set_powergating_state - set VCN block powergating state
1588  *
1589  * @handle: amdgpu_device pointer
1590  * @state: power gating state
1591  *
1592  * Set VCN block powergating state
1593  */
1594 static int vcn_v4_0_set_powergating_state(void *handle, enum amd_powergating_state state)
1595 {
1596     struct amdgpu_device *adev = (struct amdgpu_device *)handle;
1597     int ret;
1598 
1599     if(state == adev->vcn.cur_state)
1600         return 0;
1601 
1602     if (state == AMD_PG_STATE_GATE)
1603         ret = vcn_v4_0_stop(adev);
1604     else
1605         ret = vcn_v4_0_start(adev);
1606 
1607     if(!ret)
1608         adev->vcn.cur_state = state;
1609 
1610     return ret;
1611 }
1612 
1613 /**
1614  * vcn_v4_0_set_interrupt_state - set VCN block interrupt state
1615  *
1616  * @adev: amdgpu_device pointer
1617  * @source: interrupt sources
1618  * @type: interrupt types
1619  * @state: interrupt states
1620  *
1621  * Set VCN block interrupt state
1622  */
1623 static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
1624       unsigned type, enum amdgpu_interrupt_state state)
1625 {
1626     return 0;
1627 }
1628 
1629 /**
1630  * vcn_v4_0_process_interrupt - process VCN block interrupt
1631  *
1632  * @adev: amdgpu_device pointer
1633  * @source: interrupt sources
1634  * @entry: interrupt entry from clients and sources
1635  *
1636  * Process VCN block interrupt
1637  */
1638 static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,
1639       struct amdgpu_iv_entry *entry)
1640 {
1641     uint32_t ip_instance;
1642 
1643     switch (entry->client_id) {
1644     case SOC15_IH_CLIENTID_VCN:
1645         ip_instance = 0;
1646         break;
1647     case SOC15_IH_CLIENTID_VCN1:
1648         ip_instance = 1;
1649         break;
1650     default:
1651         DRM_ERROR("Unhandled client id: %d\n", entry->client_id);
1652         return 0;
1653     }
1654 
1655     DRM_DEBUG("IH: VCN TRAP\n");
1656 
1657     switch (entry->src_id) {
1658     case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
1659         amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]);
1660         break;
1661     default:
1662         DRM_ERROR("Unhandled interrupt: %d %d\n",
1663               entry->src_id, entry->src_data[0]);
1664         break;
1665     }
1666 
1667     return 0;
1668 }
1669 
1670 static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = {
1671     .set = vcn_v4_0_set_interrupt_state,
1672     .process = vcn_v4_0_process_interrupt,
1673 };
1674 
1675 /**
1676  * vcn_v4_0_set_irq_funcs - set VCN block interrupt irq functions
1677  *
1678  * @adev: amdgpu_device pointer
1679  *
1680  * Set VCN block interrupt irq functions
1681  */
1682 static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev)
1683 {
1684     int i;
1685 
1686     for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
1687         if (adev->vcn.harvest_config & (1 << i))
1688             continue;
1689 
1690         adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;
1691         adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs;
1692     }
1693 }
1694 
1695 static const struct amd_ip_funcs vcn_v4_0_ip_funcs = {
1696     .name = "vcn_v4_0",
1697     .early_init = vcn_v4_0_early_init,
1698     .late_init = NULL,
1699     .sw_init = vcn_v4_0_sw_init,
1700     .sw_fini = vcn_v4_0_sw_fini,
1701     .hw_init = vcn_v4_0_hw_init,
1702     .hw_fini = vcn_v4_0_hw_fini,
1703     .suspend = vcn_v4_0_suspend,
1704     .resume = vcn_v4_0_resume,
1705     .is_idle = vcn_v4_0_is_idle,
1706     .wait_for_idle = vcn_v4_0_wait_for_idle,
1707     .check_soft_reset = NULL,
1708     .pre_soft_reset = NULL,
1709     .soft_reset = NULL,
1710     .post_soft_reset = NULL,
1711     .set_clockgating_state = vcn_v4_0_set_clockgating_state,
1712     .set_powergating_state = vcn_v4_0_set_powergating_state,
1713 };
1714 
1715 const struct amdgpu_ip_block_version vcn_v4_0_ip_block =
1716 {
1717     .type = AMD_IP_BLOCK_TYPE_VCN,
1718     .major = 4,
1719     .minor = 0,
1720     .rev = 0,
1721     .funcs = &vcn_v4_0_ip_funcs,
1722 };