brintos

brintos / linux-shallow public Read only

0
0
Text · 52.8 KiB · 9d4f535 Raw
1709 lines · c
1/*2 * Copyright 2023 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 */23 24#include <linux/firmware.h>25#include "amdgpu.h"26#include "amdgpu_vcn.h"27#include "amdgpu_pm.h"28#include "amdgpu_cs.h"29#include "soc15.h"30#include "soc15d.h"31#include "soc15_hw_ip.h"32#include "vcn_v2_0.h"33#include "mmsch_v4_0.h"34#include "vcn_v4_0_5.h"35 36#include "vcn/vcn_4_0_5_offset.h"37#include "vcn/vcn_4_0_5_sh_mask.h"38#include "ivsrcid/vcn/irqsrcs_vcn_4_0.h"39 40#include <drm/drm_drv.h>41 42#define mmUVD_DPG_LMA_CTL							regUVD_DPG_LMA_CTL43#define mmUVD_DPG_LMA_CTL_BASE_IDX					regUVD_DPG_LMA_CTL_BASE_IDX44#define mmUVD_DPG_LMA_DATA							regUVD_DPG_LMA_DATA45#define mmUVD_DPG_LMA_DATA_BASE_IDX					regUVD_DPG_LMA_DATA_BASE_IDX46 47#define VCN_VID_SOC_ADDRESS_2_0						0x1fb0048#define VCN1_VID_SOC_ADDRESS_3_0					(0x48300 + 0x38000)49 50#define VCN_HARVEST_MMSCH							051 52#define RDECODE_MSG_CREATE							0x0000000053#define RDECODE_MESSAGE_CREATE						0x0000000154 55static const struct amdgpu_hwip_reg_entry vcn_reg_list_4_0_5[] = {56	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_POWER_STATUS),57	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_STATUS),58	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_CONTEXT_ID),59	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_CONTEXT_ID2),60	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_GPCOM_VCPU_DATA0),61	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_GPCOM_VCPU_DATA1),62	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_GPCOM_VCPU_CMD),63	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI),64	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO),65	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI2),66	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO2),67	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI3),68	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO3),69	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_HI4),70	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_BASE_LO4),71	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR),72	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR),73	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR2),74	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR2),75	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR3),76	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR3),77	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_RPTR4),78	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_WPTR4),79	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE),80	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE2),81	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE3),82	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_RB_SIZE4),83	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_PGFSM_CONFIG),84	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_PGFSM_STATUS),85	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_LMA_CTL),86	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_LMA_DATA),87	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_LMA_MASK),88	SOC15_REG_ENTRY_STR(VCN, 0, regUVD_DPG_PAUSE)89};90 91static int amdgpu_ih_clientid_vcns[] = {92	SOC15_IH_CLIENTID_VCN,93	SOC15_IH_CLIENTID_VCN194};95 96static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev);97static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev);98static int vcn_v4_0_5_set_powergating_state(void *handle,99		enum amd_powergating_state state);100static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev,101		int inst_idx, struct dpg_pause_state *new_state);102static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring);103 104/**105 * vcn_v4_0_5_early_init - set function pointers and load microcode106 *107 * @handle: amdgpu_device pointer108 *109 * Set ring and irq function pointers110 * Load microcode from filesystem111 */112static int vcn_v4_0_5_early_init(void *handle)113{114	struct amdgpu_device *adev = (struct amdgpu_device *)handle;115 116	/* re-use enc ring as unified ring */117	adev->vcn.num_enc_rings = 1;118	vcn_v4_0_5_set_unified_ring_funcs(adev);119	vcn_v4_0_5_set_irq_funcs(adev);120 121	return amdgpu_vcn_early_init(adev);122}123 124/**125 * vcn_v4_0_5_sw_init - sw init for VCN block126 *127 * @handle: amdgpu_device pointer128 *129 * Load firmware and sw initialization130 */131static int vcn_v4_0_5_sw_init(void *handle)132{133	struct amdgpu_ring *ring;134	struct amdgpu_device *adev = (struct amdgpu_device *)handle;135	int i, r;136	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_5);137	uint32_t *ptr;138 139	r = amdgpu_vcn_sw_init(adev);140	if (r)141		return r;142 143	amdgpu_vcn_setup_ucode(adev);144 145	r = amdgpu_vcn_resume(adev);146	if (r)147		return r;148 149	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {150		volatile struct amdgpu_vcn4_fw_shared *fw_shared;151 152		if (adev->vcn.harvest_config & (1 << i))153			continue;154 155		atomic_set(&adev->vcn.inst[i].sched_score, 0);156 157		/* VCN UNIFIED TRAP */158		r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],159				VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE, &adev->vcn.inst[i].irq);160		if (r)161			return r;162 163		/* VCN POISON TRAP */164		r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],165				VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].irq);166		if (r)167			return r;168 169		ring = &adev->vcn.inst[i].ring_enc[0];170		ring->use_doorbell = true;171		if (amdgpu_sriov_vf(adev))172			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +173						i * (adev->vcn.num_enc_rings + 1) + 1;174		else175			ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) +176						2 + 8 * i;177		ring->vm_hub = AMDGPU_MMHUB0(0);178		sprintf(ring->name, "vcn_unified_%d", i);179 180		r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0,181				AMDGPU_RING_PRIO_0, &adev->vcn.inst[i].sched_score);182		if (r)183			return r;184 185		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;186		fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);187		fw_shared->sq.is_enabled = 1;188 189		fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_SMU_DPM_INTERFACE_FLAG);190		fw_shared->smu_dpm_interface.smu_interface_type = (adev->flags & AMD_IS_APU) ?191			AMDGPU_VCN_SMU_DPM_INTERFACE_APU : AMDGPU_VCN_SMU_DPM_INTERFACE_DGPU;192 193		if (amdgpu_sriov_vf(adev))194			fw_shared->present_flag_0 |= cpu_to_le32(AMDGPU_VCN_VF_RB_SETUP_FLAG);195 196		if (amdgpu_vcnfw_log)197			amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);198	}199 200	if (amdgpu_sriov_vf(adev)) {201		r = amdgpu_virt_alloc_mm_table(adev);202		if (r)203			return r;204	}205 206	if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)207		adev->vcn.pause_dpg_mode = vcn_v4_0_5_pause_dpg_mode;208 209	/* Allocate memory for VCN IP Dump buffer */210	ptr = kcalloc(adev->vcn.num_vcn_inst * reg_count, sizeof(uint32_t), GFP_KERNEL);211	if (!ptr) {212		DRM_ERROR("Failed to allocate memory for VCN IP Dump\n");213		adev->vcn.ip_dump = NULL;214	} else {215		adev->vcn.ip_dump = ptr;216	}217	return 0;218}219 220/**221 * vcn_v4_0_5_sw_fini - sw fini for VCN block222 *223 * @handle: amdgpu_device pointer224 *225 * VCN suspend and free up sw allocation226 */227static int vcn_v4_0_5_sw_fini(void *handle)228{229	struct amdgpu_device *adev = (struct amdgpu_device *)handle;230	int i, r, idx;231 232	if (drm_dev_enter(adev_to_drm(adev), &idx)) {233		for (i = 0; i < adev->vcn.num_vcn_inst; i++) {234			volatile struct amdgpu_vcn4_fw_shared *fw_shared;235 236			if (adev->vcn.harvest_config & (1 << i))237				continue;238 239			fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;240			fw_shared->present_flag_0 = 0;241			fw_shared->sq.is_enabled = 0;242		}243 244		drm_dev_exit(idx);245	}246 247	if (amdgpu_sriov_vf(adev))248		amdgpu_virt_free_mm_table(adev);249 250	r = amdgpu_vcn_suspend(adev);251	if (r)252		return r;253 254	r = amdgpu_vcn_sw_fini(adev);255 256	kfree(adev->vcn.ip_dump);257 258	return r;259}260 261/**262 * vcn_v4_0_5_hw_init - start and test VCN block263 *264 * @handle: amdgpu_device pointer265 *266 * Initialize the hardware, boot up the VCPU and do some testing267 */268static int vcn_v4_0_5_hw_init(void *handle)269{270	struct amdgpu_device *adev = (struct amdgpu_device *)handle;271	struct amdgpu_ring *ring;272	int i, r;273 274	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {275		if (adev->vcn.harvest_config & (1 << i))276			continue;277 278		ring = &adev->vcn.inst[i].ring_enc[0];279 280		adev->nbio.funcs->vcn_doorbell_range(adev, ring->use_doorbell,281				((adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i), i);282 283		r = amdgpu_ring_test_helper(ring);284		if (r)285			return r;286	}287 288	return 0;289}290 291/**292 * vcn_v4_0_5_hw_fini - stop the hardware block293 *294 * @handle: amdgpu_device pointer295 *296 * Stop the VCN block, mark ring as not ready any more297 */298static int vcn_v4_0_5_hw_fini(void *handle)299{300	struct amdgpu_device *adev = (struct amdgpu_device *)handle;301	int i;302 303	cancel_delayed_work_sync(&adev->vcn.idle_work);304 305	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {306		if (adev->vcn.harvest_config & (1 << i))307			continue;308		if (!amdgpu_sriov_vf(adev)) {309			if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||310				(adev->vcn.cur_state != AMD_PG_STATE_GATE &&311				RREG32_SOC15(VCN, i, regUVD_STATUS))) {312				vcn_v4_0_5_set_powergating_state(adev, AMD_PG_STATE_GATE);313			}314		}315	}316 317	return 0;318}319 320/**321 * vcn_v4_0_5_suspend - suspend VCN block322 *323 * @handle: amdgpu_device pointer324 *325 * HW fini and suspend VCN block326 */327static int vcn_v4_0_5_suspend(void *handle)328{329	int r;330	struct amdgpu_device *adev = (struct amdgpu_device *)handle;331 332	r = vcn_v4_0_5_hw_fini(adev);333	if (r)334		return r;335 336	r = amdgpu_vcn_suspend(adev);337 338	return r;339}340 341/**342 * vcn_v4_0_5_resume - resume VCN block343 *344 * @handle: amdgpu_device pointer345 *346 * Resume firmware and hw init VCN block347 */348static int vcn_v4_0_5_resume(void *handle)349{350	int r;351	struct amdgpu_device *adev = (struct amdgpu_device *)handle;352 353	r = amdgpu_vcn_resume(adev);354	if (r)355		return r;356 357	r = vcn_v4_0_5_hw_init(adev);358 359	return r;360}361 362/**363 * vcn_v4_0_5_mc_resume - memory controller programming364 *365 * @adev: amdgpu_device pointer366 * @inst: instance number367 *368 * Let the VCN memory controller know it's offsets369 */370static void vcn_v4_0_5_mc_resume(struct amdgpu_device *adev, int inst)371{372	uint32_t offset, size;373	const struct common_firmware_header *hdr;374 375	hdr = (const struct common_firmware_header *)adev->vcn.fw[inst]->data;376	size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);377 378	/* cache window 0: fw */379	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {380		WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,381			(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_lo));382		WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,383			(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst].tmr_mc_addr_hi));384		WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, 0);385		offset = 0;386	} else {387		WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,388			lower_32_bits(adev->vcn.inst[inst].gpu_addr));389		WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,390			upper_32_bits(adev->vcn.inst[inst].gpu_addr));391		offset = size;392		WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET0, AMDGPU_UVD_FIRMWARE_OFFSET >> 3);393	}394	WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE0, size);395 396	/* cache window 1: stack */397	WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,398		lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset));399	WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,400		upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset));401	WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET1, 0);402	WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);403 404	/* cache window 2: context */405	WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,406		lower_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));407	WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,408		upper_32_bits(adev->vcn.inst[inst].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));409	WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_OFFSET2, 0);410	WREG32_SOC15(VCN, inst, regUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);411 412	/* non-cache window */413	WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW,414		lower_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));415	WREG32_SOC15(VCN, inst, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH,416		upper_32_bits(adev->vcn.inst[inst].fw_shared.gpu_addr));417	WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_OFFSET0, 0);418	WREG32_SOC15(VCN, inst, regUVD_VCPU_NONCACHE_SIZE0,419		AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)));420}421 422/**423 * vcn_v4_0_5_mc_resume_dpg_mode - memory controller programming for dpg mode424 *425 * @adev: amdgpu_device pointer426 * @inst_idx: instance number index427 * @indirect: indirectly write sram428 *429 * Let the VCN memory controller know it's offsets with dpg mode430 */431static void vcn_v4_0_5_mc_resume_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)432{433	uint32_t offset, size;434	const struct common_firmware_header *hdr;435 436	hdr = (const struct common_firmware_header *)adev->vcn.fw[inst_idx]->data;437	size = AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);438 439	/* cache window 0: fw */440	if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {441		if (!indirect) {442			WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(443			VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),444			(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_lo),445			0, indirect);446			WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(447			VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),448			(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN + inst_idx].tmr_mc_addr_hi),449			0, indirect);450			WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(451				VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);452		} else {453			WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(454			VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW), 0, 0, indirect);455			WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(456			VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH), 0, 0, indirect);457			WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(458				VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0), 0, 0, indirect);459		}460		offset = 0;461	} else {462		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(463			VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),464			lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);465		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(466			VCN, inst_idx, regUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),467			upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr), 0, indirect);468		offset = size;469		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(470			VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET0),471			AMDGPU_UVD_FIRMWARE_OFFSET >> 3, 0, indirect);472	}473 474	if (!indirect)475		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(476			VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), size, 0, indirect);477	else478		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(479			VCN, inst_idx, regUVD_VCPU_CACHE_SIZE0), 0, 0, indirect);480 481	/* cache window 1: stack */482	if (!indirect) {483		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(484			VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),485			lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);486		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(487			VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),488			upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset), 0, indirect);489		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(490			VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);491	} else {492		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(493			VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW), 0, 0, indirect);494		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(495			VCN, inst_idx, regUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH), 0, 0, indirect);496		WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(497			VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET1), 0, 0, indirect);498	}499 500	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(501		VCN, inst_idx, regUVD_VCPU_CACHE_SIZE1), AMDGPU_VCN_STACK_SIZE, 0, indirect);502 503	/* cache window 2: context */504	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(505		VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),506		lower_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),507		0, indirect);508	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(509		VCN, inst_idx, regUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),510		upper_32_bits(adev->vcn.inst[inst_idx].gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),511		0, indirect);512	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(513		VCN, inst_idx, regUVD_VCPU_CACHE_OFFSET2), 0, 0, indirect);514	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(515		VCN, inst_idx, regUVD_VCPU_CACHE_SIZE2), AMDGPU_VCN_CONTEXT_SIZE, 0, indirect);516 517	/* non-cache window */518	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(519		VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_LOW),520		lower_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);521	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(522		VCN, inst_idx, regUVD_LMI_VCPU_NC0_64BIT_BAR_HIGH),523		upper_32_bits(adev->vcn.inst[inst_idx].fw_shared.gpu_addr), 0, indirect);524	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(525		VCN, inst_idx, regUVD_VCPU_NONCACHE_OFFSET0), 0, 0, indirect);526	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(527		VCN, inst_idx, regUVD_VCPU_NONCACHE_SIZE0),528		AMDGPU_GPU_PAGE_ALIGN(sizeof(struct amdgpu_vcn4_fw_shared)), 0, indirect);529 530	/* VCN global tiling registers */531	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(532		VCN, inst_idx, regUVD_GFX10_ADDR_CONFIG),533		adev->gfx.config.gb_addr_config, 0, indirect);534}535 536/**537 * vcn_v4_0_5_disable_static_power_gating - disable VCN static power gating538 *539 * @adev: amdgpu_device pointer540 * @inst: instance number541 *542 * Disable static power gating for VCN block543 */544static void vcn_v4_0_5_disable_static_power_gating(struct amdgpu_device *adev, int inst)545{546	uint32_t data = 0;547 548	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {549		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,550					1 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT);551		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS, 0,552					UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);553		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,554					2 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT);555		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,556					1 << UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS__SHIFT,557					UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);558		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,559					2 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT);560		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,561					1 << UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS__SHIFT,562					UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);563		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,564					2 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT);565		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,566					1 << UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS__SHIFT,567					UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);568	} else {569		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,570			1 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT);571		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,572			0, UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);573		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,574			1 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT);575		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,576			0, UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);577		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,578			1 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT);579		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,580			0, UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);581		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,582			1 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT);583		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,584			0, UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);585	}586 587	data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);588	data &= ~0x103;589	if (adev->pg_flags & AMD_PG_SUPPORT_VCN)590		data |= UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON |591			UVD_POWER_STATUS__UVD_PG_EN_MASK;592	WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);593}594 595/**596 * vcn_v4_0_5_enable_static_power_gating - enable VCN static power gating597 *598 * @adev: amdgpu_device pointer599 * @inst: instance number600 *601 * Enable static power gating for VCN block602 */603static void vcn_v4_0_5_enable_static_power_gating(struct amdgpu_device *adev, int inst)604{605	uint32_t data;606 607	if (adev->pg_flags & AMD_PG_SUPPORT_VCN) {608		/* Before power off, this indicator has to be turned on */609		data = RREG32_SOC15(VCN, inst, regUVD_POWER_STATUS);610		data &= ~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK;611		data |= UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF;612		WREG32_SOC15(VCN, inst, regUVD_POWER_STATUS, data);613 614		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,615			2 << UVD_IPX_DLDO_CONFIG__ONO5_PWR_CONFIG__SHIFT);616		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,617			1 << UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS__SHIFT,618			UVD_IPX_DLDO_STATUS__ONO5_PWR_STATUS_MASK);619		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,620			2 << UVD_IPX_DLDO_CONFIG__ONO4_PWR_CONFIG__SHIFT);621		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,622			1 << UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS__SHIFT,623			UVD_IPX_DLDO_STATUS__ONO4_PWR_STATUS_MASK);624		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,625			2 << UVD_IPX_DLDO_CONFIG__ONO3_PWR_CONFIG__SHIFT);626		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,627			1 << UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS__SHIFT,628			UVD_IPX_DLDO_STATUS__ONO3_PWR_STATUS_MASK);629		WREG32_SOC15(VCN, inst, regUVD_IPX_DLDO_CONFIG,630			2 << UVD_IPX_DLDO_CONFIG__ONO2_PWR_CONFIG__SHIFT);631		SOC15_WAIT_ON_RREG(VCN, inst, regUVD_IPX_DLDO_STATUS,632			1 << UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS__SHIFT,633			UVD_IPX_DLDO_STATUS__ONO2_PWR_STATUS_MASK);634	}635}636 637/**638 * vcn_v4_0_5_disable_clock_gating - disable VCN clock gating639 *640 * @adev: amdgpu_device pointer641 * @inst: instance number642 *643 * Disable clock gating for VCN block644 */645static void vcn_v4_0_5_disable_clock_gating(struct amdgpu_device *adev, int inst)646{647	uint32_t data;648 649	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)650		return;651 652	/* VCN disable CGC */653	data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);654	data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;655	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;656	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;657	WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);658 659	data = RREG32_SOC15(VCN, inst, regUVD_CGC_GATE);660	data &= ~(UVD_CGC_GATE__SYS_MASK661		| UVD_CGC_GATE__UDEC_MASK662		| UVD_CGC_GATE__MPEG2_MASK663		| UVD_CGC_GATE__REGS_MASK664		| UVD_CGC_GATE__RBC_MASK665		| UVD_CGC_GATE__LMI_MC_MASK666		| UVD_CGC_GATE__LMI_UMC_MASK667		| UVD_CGC_GATE__IDCT_MASK668		| UVD_CGC_GATE__MPRD_MASK669		| UVD_CGC_GATE__MPC_MASK670		| UVD_CGC_GATE__LBSI_MASK671		| UVD_CGC_GATE__LRBBM_MASK672		| UVD_CGC_GATE__UDEC_RE_MASK673		| UVD_CGC_GATE__UDEC_CM_MASK674		| UVD_CGC_GATE__UDEC_IT_MASK675		| UVD_CGC_GATE__UDEC_DB_MASK676		| UVD_CGC_GATE__UDEC_MP_MASK677		| UVD_CGC_GATE__WCB_MASK678		| UVD_CGC_GATE__VCPU_MASK679		| UVD_CGC_GATE__MMSCH_MASK);680 681	WREG32_SOC15(VCN, inst, regUVD_CGC_GATE, data);682	SOC15_WAIT_ON_RREG(VCN, inst, regUVD_CGC_GATE, 0,  0xFFFFFFFF);683 684	data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);685	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK686		| UVD_CGC_CTRL__UDEC_CM_MODE_MASK687		| UVD_CGC_CTRL__UDEC_IT_MODE_MASK688		| UVD_CGC_CTRL__UDEC_DB_MODE_MASK689		| UVD_CGC_CTRL__UDEC_MP_MODE_MASK690		| UVD_CGC_CTRL__SYS_MODE_MASK691		| UVD_CGC_CTRL__UDEC_MODE_MASK692		| UVD_CGC_CTRL__MPEG2_MODE_MASK693		| UVD_CGC_CTRL__REGS_MODE_MASK694		| UVD_CGC_CTRL__RBC_MODE_MASK695		| UVD_CGC_CTRL__LMI_MC_MODE_MASK696		| UVD_CGC_CTRL__LMI_UMC_MODE_MASK697		| UVD_CGC_CTRL__IDCT_MODE_MASK698		| UVD_CGC_CTRL__MPRD_MODE_MASK699		| UVD_CGC_CTRL__MPC_MODE_MASK700		| UVD_CGC_CTRL__LBSI_MODE_MASK701		| UVD_CGC_CTRL__LRBBM_MODE_MASK702		| UVD_CGC_CTRL__WCB_MODE_MASK703		| UVD_CGC_CTRL__VCPU_MODE_MASK704		| UVD_CGC_CTRL__MMSCH_MODE_MASK);705	WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);706 707	data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE);708	data |= (UVD_SUVD_CGC_GATE__SRE_MASK709		| UVD_SUVD_CGC_GATE__SIT_MASK710		| UVD_SUVD_CGC_GATE__SMP_MASK711		| UVD_SUVD_CGC_GATE__SCM_MASK712		| UVD_SUVD_CGC_GATE__SDB_MASK713		| UVD_SUVD_CGC_GATE__SRE_H264_MASK714		| UVD_SUVD_CGC_GATE__SRE_HEVC_MASK715		| UVD_SUVD_CGC_GATE__SIT_H264_MASK716		| UVD_SUVD_CGC_GATE__SIT_HEVC_MASK717		| UVD_SUVD_CGC_GATE__SCM_H264_MASK718		| UVD_SUVD_CGC_GATE__SCM_HEVC_MASK719		| UVD_SUVD_CGC_GATE__SDB_H264_MASK720		| UVD_SUVD_CGC_GATE__SDB_HEVC_MASK721		| UVD_SUVD_CGC_GATE__SCLR_MASK722		| UVD_SUVD_CGC_GATE__UVD_SC_MASK723		| UVD_SUVD_CGC_GATE__ENT_MASK724		| UVD_SUVD_CGC_GATE__SIT_HEVC_DEC_MASK725		| UVD_SUVD_CGC_GATE__SIT_HEVC_ENC_MASK726		| UVD_SUVD_CGC_GATE__SITE_MASK727		| UVD_SUVD_CGC_GATE__SRE_VP9_MASK728		| UVD_SUVD_CGC_GATE__SCM_VP9_MASK729		| UVD_SUVD_CGC_GATE__SIT_VP9_DEC_MASK730		| UVD_SUVD_CGC_GATE__SDB_VP9_MASK731		| UVD_SUVD_CGC_GATE__IME_HEVC_MASK);732	WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_GATE, data);733 734	data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL);735	data &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK736		| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK737		| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK738		| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK739		| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK740		| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK741		| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK742		| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK743		| UVD_SUVD_CGC_CTRL__IME_MODE_MASK744		| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);745	WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);746}747 748/**749 * vcn_v4_0_5_disable_clock_gating_dpg_mode - disable VCN clock gating dpg mode750 *751 * @adev: amdgpu_device pointer752 * @sram_sel: sram select753 * @inst_idx: instance number index754 * @indirect: indirectly write sram755 *756 * Disable clock gating for VCN block with dpg mode757 */758static void vcn_v4_0_5_disable_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t sram_sel,759		int inst_idx, uint8_t indirect)760{761	uint32_t reg_data = 0;762 763	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)764		return;765 766	/* enable sw clock gating control */767	reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;768	reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;769	reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;770	reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |771		 UVD_CGC_CTRL__UDEC_CM_MODE_MASK |772		 UVD_CGC_CTRL__UDEC_IT_MODE_MASK |773		 UVD_CGC_CTRL__UDEC_DB_MODE_MASK |774		 UVD_CGC_CTRL__UDEC_MP_MODE_MASK |775		 UVD_CGC_CTRL__SYS_MODE_MASK |776		 UVD_CGC_CTRL__UDEC_MODE_MASK |777		 UVD_CGC_CTRL__MPEG2_MODE_MASK |778		 UVD_CGC_CTRL__REGS_MODE_MASK |779		 UVD_CGC_CTRL__RBC_MODE_MASK |780		 UVD_CGC_CTRL__LMI_MC_MODE_MASK |781		 UVD_CGC_CTRL__LMI_UMC_MODE_MASK |782		 UVD_CGC_CTRL__IDCT_MODE_MASK |783		 UVD_CGC_CTRL__MPRD_MODE_MASK |784		 UVD_CGC_CTRL__MPC_MODE_MASK |785		 UVD_CGC_CTRL__LBSI_MODE_MASK |786		 UVD_CGC_CTRL__LRBBM_MODE_MASK |787		 UVD_CGC_CTRL__WCB_MODE_MASK |788		 UVD_CGC_CTRL__VCPU_MODE_MASK);789	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(790		VCN, inst_idx, regUVD_CGC_CTRL), reg_data, sram_sel, indirect);791 792	/* turn off clock gating */793	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(794		VCN, inst_idx, regUVD_CGC_GATE), 0, sram_sel, indirect);795 796	/* turn on SUVD clock gating */797	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(798		VCN, inst_idx, regUVD_SUVD_CGC_GATE), 1, sram_sel, indirect);799 800	/* turn on sw mode in UVD_SUVD_CGC_CTRL */801	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(802		VCN, inst_idx, regUVD_SUVD_CGC_CTRL), 0, sram_sel, indirect);803}804 805/**806 * vcn_v4_0_5_enable_clock_gating - enable VCN clock gating807 *808 * @adev: amdgpu_device pointer809 * @inst: instance number810 *811 * Enable clock gating for VCN block812 */813static void vcn_v4_0_5_enable_clock_gating(struct amdgpu_device *adev, int inst)814{815	uint32_t data;816 817	if (adev->cg_flags & AMD_CG_SUPPORT_VCN_MGCG)818		return;819 820	/* enable VCN CGC */821	data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);822	data |= 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;823	data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;824	data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;825	WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);826 827	data = RREG32_SOC15(VCN, inst, regUVD_CGC_CTRL);828	data |= (UVD_CGC_CTRL__UDEC_RE_MODE_MASK829		| UVD_CGC_CTRL__UDEC_CM_MODE_MASK830		| UVD_CGC_CTRL__UDEC_IT_MODE_MASK831		| UVD_CGC_CTRL__UDEC_DB_MODE_MASK832		| UVD_CGC_CTRL__UDEC_MP_MODE_MASK833		| UVD_CGC_CTRL__SYS_MODE_MASK834		| UVD_CGC_CTRL__UDEC_MODE_MASK835		| UVD_CGC_CTRL__MPEG2_MODE_MASK836		| UVD_CGC_CTRL__REGS_MODE_MASK837		| UVD_CGC_CTRL__RBC_MODE_MASK838		| UVD_CGC_CTRL__LMI_MC_MODE_MASK839		| UVD_CGC_CTRL__LMI_UMC_MODE_MASK840		| UVD_CGC_CTRL__IDCT_MODE_MASK841		| UVD_CGC_CTRL__MPRD_MODE_MASK842		| UVD_CGC_CTRL__MPC_MODE_MASK843		| UVD_CGC_CTRL__LBSI_MODE_MASK844		| UVD_CGC_CTRL__LRBBM_MODE_MASK845		| UVD_CGC_CTRL__WCB_MODE_MASK846		| UVD_CGC_CTRL__VCPU_MODE_MASK847		| UVD_CGC_CTRL__MMSCH_MODE_MASK);848	WREG32_SOC15(VCN, inst, regUVD_CGC_CTRL, data);849 850	data = RREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL);851	data |= (UVD_SUVD_CGC_CTRL__SRE_MODE_MASK852		| UVD_SUVD_CGC_CTRL__SIT_MODE_MASK853		| UVD_SUVD_CGC_CTRL__SMP_MODE_MASK854		| UVD_SUVD_CGC_CTRL__SCM_MODE_MASK855		| UVD_SUVD_CGC_CTRL__SDB_MODE_MASK856		| UVD_SUVD_CGC_CTRL__SCLR_MODE_MASK857		| UVD_SUVD_CGC_CTRL__UVD_SC_MODE_MASK858		| UVD_SUVD_CGC_CTRL__ENT_MODE_MASK859		| UVD_SUVD_CGC_CTRL__IME_MODE_MASK860		| UVD_SUVD_CGC_CTRL__SITE_MODE_MASK);861	WREG32_SOC15(VCN, inst, regUVD_SUVD_CGC_CTRL, data);862}863 864/**865 * vcn_v4_0_5_start_dpg_mode - VCN start with dpg mode866 *867 * @adev: amdgpu_device pointer868 * @inst_idx: instance number index869 * @indirect: indirectly write sram870 *871 * Start VCN block with dpg mode872 */873static int vcn_v4_0_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)874{875	volatile struct amdgpu_vcn4_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;876	struct amdgpu_ring *ring;877	uint32_t tmp;878 879	/* disable register anti-hang mechanism */880	WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 1,881		~UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);882	/* enable dynamic power gating mode */883	tmp = RREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS);884	tmp |= UVD_POWER_STATUS__UVD_PG_MODE_MASK;885	tmp |= UVD_POWER_STATUS__UVD_PG_EN_MASK;886	WREG32_SOC15(VCN, inst_idx, regUVD_POWER_STATUS, tmp);887 888	if (indirect)889		adev->vcn.inst[inst_idx].dpg_sram_curr_addr =890					(uint32_t *)adev->vcn.inst[inst_idx].dpg_sram_cpu_addr;891 892	/* enable clock gating */893	vcn_v4_0_5_disable_clock_gating_dpg_mode(adev, 0, inst_idx, indirect);894 895	/* enable VCPU clock */896	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);897	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK | UVD_VCPU_CNTL__BLK_RST_MASK;898	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(899		VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);900 901	/* disable master interrupt */902	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(903		VCN, inst_idx, regUVD_MASTINT_EN), 0, 0, indirect);904 905	/* setup regUVD_LMI_CTRL */906	tmp = (UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |907		UVD_LMI_CTRL__REQ_MODE_MASK |908		UVD_LMI_CTRL__CRC_RESET_MASK |909		UVD_LMI_CTRL__MASK_MC_URGENT_MASK |910		UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |911		UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |912		(8 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |913		0x00100000L);914	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(915		VCN, inst_idx, regUVD_LMI_CTRL), tmp, 0, indirect);916 917	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(918		VCN, inst_idx, regUVD_MPC_CNTL),919		0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT, 0, indirect);920 921	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(922		VCN, inst_idx, regUVD_MPC_SET_MUXA0),923		((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |924		 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |925		 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |926		 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)), 0, indirect);927 928	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(929		VCN, inst_idx, regUVD_MPC_SET_MUXB0),930		 ((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |931		 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |932		 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |933		 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)), 0, indirect);934 935	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(936		VCN, inst_idx, regUVD_MPC_SET_MUX),937		((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |938		 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |939		 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)), 0, indirect);940 941	vcn_v4_0_5_mc_resume_dpg_mode(adev, inst_idx, indirect);942 943	tmp = (0xFF << UVD_VCPU_CNTL__PRB_TIMEOUT_VAL__SHIFT);944	tmp |= UVD_VCPU_CNTL__CLK_EN_MASK;945	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(946		VCN, inst_idx, regUVD_VCPU_CNTL), tmp, 0, indirect);947 948	/* enable LMI MC and UMC channels */949	tmp = 0x1f << UVD_LMI_CTRL2__RE_OFLD_MIF_WR_REQ_NUM__SHIFT;950	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(951		VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);952 953	/* enable master interrupt */954	WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(955		VCN, inst_idx, regUVD_MASTINT_EN),956		UVD_MASTINT_EN__VCPU_EN_MASK, 0, indirect);957 958	if (indirect)959		amdgpu_vcn_psp_update_sram(adev, inst_idx, 0);960 961	ring = &adev->vcn.inst[inst_idx].ring_enc[0];962 963	WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_LO, ring->gpu_addr);964	WREG32_SOC15(VCN, inst_idx, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));965	WREG32_SOC15(VCN, inst_idx, regUVD_RB_SIZE, ring->ring_size / 4);966 967	tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);968	tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);969	WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);970	fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;971	WREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR, 0);972	WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, 0);973 974	tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_RPTR);975	WREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR, tmp);976	ring->wptr = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);977 978	tmp = RREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE);979	tmp |= VCN_RB_ENABLE__RB1_EN_MASK;980	WREG32_SOC15(VCN, inst_idx, regVCN_RB_ENABLE, tmp);981	fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);982 983	WREG32_SOC15(VCN, inst_idx, regVCN_RB1_DB_CTRL,984			ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |985			VCN_RB1_DB_CTRL__EN_MASK);986 987	return 0;988}989 990 991/**992 * vcn_v4_0_5_start - VCN start993 *994 * @adev: amdgpu_device pointer995 *996 * Start VCN block997 */998static int vcn_v4_0_5_start(struct amdgpu_device *adev)999{1000	volatile struct amdgpu_vcn4_fw_shared *fw_shared;1001	struct amdgpu_ring *ring;1002	uint32_t tmp;1003	int i, j, k, r;1004 1005	if (adev->pm.dpm_enabled)1006		amdgpu_dpm_enable_uvd(adev, true);1007 1008	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1009		if (adev->vcn.harvest_config & (1 << i))1010			continue;1011 1012		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;1013 1014		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {1015			r = vcn_v4_0_5_start_dpg_mode(adev, i, adev->vcn.indirect_sram);1016			continue;1017		}1018 1019		/* disable VCN power gating */1020		vcn_v4_0_5_disable_static_power_gating(adev, i);1021 1022		/* set VCN status busy */1023		tmp = RREG32_SOC15(VCN, i, regUVD_STATUS) | UVD_STATUS__UVD_BUSY;1024		WREG32_SOC15(VCN, i, regUVD_STATUS, tmp);1025 1026		/*SW clock gating */1027		vcn_v4_0_5_disable_clock_gating(adev, i);1028 1029		/* enable VCPU clock */1030		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),1031				UVD_VCPU_CNTL__CLK_EN_MASK, ~UVD_VCPU_CNTL__CLK_EN_MASK);1032 1033		/* disable master interrupt */1034		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN), 0,1035				~UVD_MASTINT_EN__VCPU_EN_MASK);1036 1037		/* enable LMI MC and UMC channels */1038		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_LMI_CTRL2), 0,1039				~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);1040 1041		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);1042		tmp &= ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;1043		tmp &= ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;1044		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);1045 1046		/* setup regUVD_LMI_CTRL */1047		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL);1048		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL, tmp |1049				UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |1050				UVD_LMI_CTRL__MASK_MC_URGENT_MASK |1051				UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |1052				UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK);1053 1054		/* setup regUVD_MPC_CNTL */1055		tmp = RREG32_SOC15(VCN, i, regUVD_MPC_CNTL);1056		tmp &= ~UVD_MPC_CNTL__REPLACEMENT_MODE_MASK;1057		tmp |= 0x2 << UVD_MPC_CNTL__REPLACEMENT_MODE__SHIFT;1058		WREG32_SOC15(VCN, i, regUVD_MPC_CNTL, tmp);1059 1060		/* setup UVD_MPC_SET_MUXA0 */1061		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXA0,1062				((0x1 << UVD_MPC_SET_MUXA0__VARA_1__SHIFT) |1063				 (0x2 << UVD_MPC_SET_MUXA0__VARA_2__SHIFT) |1064				 (0x3 << UVD_MPC_SET_MUXA0__VARA_3__SHIFT) |1065				 (0x4 << UVD_MPC_SET_MUXA0__VARA_4__SHIFT)));1066 1067		/* setup UVD_MPC_SET_MUXB0 */1068		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUXB0,1069				((0x1 << UVD_MPC_SET_MUXB0__VARB_1__SHIFT) |1070				 (0x2 << UVD_MPC_SET_MUXB0__VARB_2__SHIFT) |1071				 (0x3 << UVD_MPC_SET_MUXB0__VARB_3__SHIFT) |1072				 (0x4 << UVD_MPC_SET_MUXB0__VARB_4__SHIFT)));1073 1074		/* setup UVD_MPC_SET_MUX */1075		WREG32_SOC15(VCN, i, regUVD_MPC_SET_MUX,1076				((0x0 << UVD_MPC_SET_MUX__SET_0__SHIFT) |1077				 (0x1 << UVD_MPC_SET_MUX__SET_1__SHIFT) |1078				 (0x2 << UVD_MPC_SET_MUX__SET_2__SHIFT)));1079 1080		vcn_v4_0_5_mc_resume(adev, i);1081 1082		/* VCN global tiling registers */1083		WREG32_SOC15(VCN, i, regUVD_GFX10_ADDR_CONFIG,1084				adev->gfx.config.gb_addr_config);1085 1086		/* unblock VCPU register access */1087		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL), 0,1088				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);1089 1090		/* release VCPU reset to boot */1091		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,1092				~UVD_VCPU_CNTL__BLK_RST_MASK);1093 1094		for (j = 0; j < 10; ++j) {1095			uint32_t status;1096 1097			for (k = 0; k < 100; ++k) {1098				status = RREG32_SOC15(VCN, i, regUVD_STATUS);1099				if (status & 2)1100					break;1101				mdelay(10);1102				if (amdgpu_emu_mode == 1)1103					msleep(1);1104			}1105 1106			if (amdgpu_emu_mode == 1) {1107				r = -1;1108				if (status & 2) {1109					r = 0;1110					break;1111				}1112			} else {1113				r = 0;1114				if (status & 2)1115					break;1116 1117				dev_err(adev->dev,1118					"VCN[%d] is not responding, trying to reset VCPU!!!\n", i);1119				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),1120							UVD_VCPU_CNTL__BLK_RST_MASK,1121							~UVD_VCPU_CNTL__BLK_RST_MASK);1122				mdelay(10);1123				WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,1124						~UVD_VCPU_CNTL__BLK_RST_MASK);1125 1126				mdelay(10);1127				r = -1;1128			}1129		}1130 1131		if (r) {1132			dev_err(adev->dev, "VCN[%d] is not responding, giving up!!!\n", i);1133			return r;1134		}1135 1136		/* enable master interrupt */1137		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_MASTINT_EN),1138				UVD_MASTINT_EN__VCPU_EN_MASK,1139				~UVD_MASTINT_EN__VCPU_EN_MASK);1140 1141		/* clear the busy bit of VCN_STATUS */1142		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_STATUS), 0,1143				~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));1144 1145		ring = &adev->vcn.inst[i].ring_enc[0];1146		WREG32_SOC15(VCN, i, regVCN_RB1_DB_CTRL,1147				ring->doorbell_index << VCN_RB1_DB_CTRL__OFFSET__SHIFT |1148				VCN_RB1_DB_CTRL__EN_MASK);1149 1150		WREG32_SOC15(VCN, i, regUVD_RB_BASE_LO, ring->gpu_addr);1151		WREG32_SOC15(VCN, i, regUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));1152		WREG32_SOC15(VCN, i, regUVD_RB_SIZE, ring->ring_size / 4);1153 1154		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);1155		tmp &= ~(VCN_RB_ENABLE__RB1_EN_MASK);1156		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);1157		fw_shared->sq.queue_mode |= FW_QUEUE_RING_RESET;1158		WREG32_SOC15(VCN, i, regUVD_RB_RPTR, 0);1159		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, 0);1160 1161		tmp = RREG32_SOC15(VCN, i, regUVD_RB_RPTR);1162		WREG32_SOC15(VCN, i, regUVD_RB_WPTR, tmp);1163		ring->wptr = RREG32_SOC15(VCN, i, regUVD_RB_WPTR);1164 1165		tmp = RREG32_SOC15(VCN, i, regVCN_RB_ENABLE);1166		tmp |= VCN_RB_ENABLE__RB1_EN_MASK;1167		WREG32_SOC15(VCN, i, regVCN_RB_ENABLE, tmp);1168		fw_shared->sq.queue_mode &= ~(FW_QUEUE_RING_RESET | FW_QUEUE_DPG_HOLD_OFF);1169	}1170 1171	return 0;1172}1173 1174/**1175 * vcn_v4_0_5_stop_dpg_mode - VCN stop with dpg mode1176 *1177 * @adev: amdgpu_device pointer1178 * @inst_idx: instance number index1179 *1180 * Stop VCN block with dpg mode1181 */1182static void vcn_v4_0_5_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx)1183{1184	uint32_t tmp;1185 1186	/* Wait for power status to be 1 */1187	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,1188		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);1189 1190	/* wait for read ptr to be equal to write ptr */1191	tmp = RREG32_SOC15(VCN, inst_idx, regUVD_RB_WPTR);1192	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_RB_RPTR, tmp, 0xFFFFFFFF);1193 1194	SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 1,1195		UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);1196 1197	/* disable dynamic power gating mode */1198	WREG32_P(SOC15_REG_OFFSET(VCN, inst_idx, regUVD_POWER_STATUS), 0,1199		~UVD_POWER_STATUS__UVD_PG_MODE_MASK);1200}1201 1202/**1203 * vcn_v4_0_5_stop - VCN stop1204 *1205 * @adev: amdgpu_device pointer1206 *1207 * Stop VCN block1208 */1209static int vcn_v4_0_5_stop(struct amdgpu_device *adev)1210{1211	volatile struct amdgpu_vcn4_fw_shared *fw_shared;1212	uint32_t tmp;1213	int i, r = 0;1214 1215	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1216		if (adev->vcn.harvest_config & (1 << i))1217			continue;1218 1219		fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;1220		fw_shared->sq.queue_mode |= FW_QUEUE_DPG_HOLD_OFF;1221 1222		if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) {1223			vcn_v4_0_5_stop_dpg_mode(adev, i);1224			continue;1225		}1226 1227		/* wait for vcn idle */1228		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE, 0x7);1229		if (r)1230			return r;1231 1232		tmp = UVD_LMI_STATUS__VCPU_LMI_WRITE_CLEAN_MASK |1233			UVD_LMI_STATUS__READ_CLEAN_MASK |1234			UVD_LMI_STATUS__WRITE_CLEAN_MASK |1235			UVD_LMI_STATUS__WRITE_CLEAN_RAW_MASK;1236		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);1237		if (r)1238			return r;1239 1240		/* disable LMI UMC channel */1241		tmp = RREG32_SOC15(VCN, i, regUVD_LMI_CTRL2);1242		tmp |= UVD_LMI_CTRL2__STALL_ARB_UMC_MASK;1243		WREG32_SOC15(VCN, i, regUVD_LMI_CTRL2, tmp);1244		tmp = UVD_LMI_STATUS__UMC_READ_CLEAN_RAW_MASK |1245			UVD_LMI_STATUS__UMC_WRITE_CLEAN_RAW_MASK;1246		r = SOC15_WAIT_ON_RREG(VCN, i, regUVD_LMI_STATUS, tmp, tmp);1247		if (r)1248			return r;1249 1250		/* block VCPU register access */1251		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_RB_ARB_CTRL),1252				UVD_RB_ARB_CTRL__VCPU_DIS_MASK,1253				~UVD_RB_ARB_CTRL__VCPU_DIS_MASK);1254 1255		/* reset VCPU */1256		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL),1257				UVD_VCPU_CNTL__BLK_RST_MASK,1258				~UVD_VCPU_CNTL__BLK_RST_MASK);1259 1260		/* disable VCPU clock */1261		WREG32_P(SOC15_REG_OFFSET(VCN, i, regUVD_VCPU_CNTL), 0,1262				~(UVD_VCPU_CNTL__CLK_EN_MASK));1263 1264		/* apply soft reset */1265		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);1266		tmp |= UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK;1267		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);1268		tmp = RREG32_SOC15(VCN, i, regUVD_SOFT_RESET);1269		tmp |= UVD_SOFT_RESET__LMI_SOFT_RESET_MASK;1270		WREG32_SOC15(VCN, i, regUVD_SOFT_RESET, tmp);1271 1272		/* clear status */1273		WREG32_SOC15(VCN, i, regUVD_STATUS, 0);1274 1275		/* apply HW clock gating */1276		vcn_v4_0_5_enable_clock_gating(adev, i);1277 1278		/* enable VCN power gating */1279		vcn_v4_0_5_enable_static_power_gating(adev, i);1280	}1281 1282	if (adev->pm.dpm_enabled)1283		amdgpu_dpm_enable_uvd(adev, false);1284 1285	return 0;1286}1287 1288/**1289 * vcn_v4_0_5_pause_dpg_mode - VCN pause with dpg mode1290 *1291 * @adev: amdgpu_device pointer1292 * @inst_idx: instance number index1293 * @new_state: pause state1294 *1295 * Pause dpg mode for VCN block1296 */1297static int vcn_v4_0_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx,1298		struct dpg_pause_state *new_state)1299{1300	uint32_t reg_data = 0;1301	int ret_code;1302 1303	/* pause/unpause if state is changed */1304	if (adev->vcn.inst[inst_idx].pause_state.fw_based != new_state->fw_based) {1305		DRM_DEV_DEBUG(adev->dev, "dpg pause state changed %d -> %d",1306			adev->vcn.inst[inst_idx].pause_state.fw_based,	new_state->fw_based);1307		reg_data = RREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE) &1308			(~UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);1309 1310		if (new_state->fw_based == VCN_DPG_STATE__PAUSE) {1311			ret_code = SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS, 0x1,1312				UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);1313 1314			if (!ret_code) {1315				/* pause DPG */1316				reg_data |= UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;1317				WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);1318 1319				/* wait for ACK */1320				SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_DPG_PAUSE,1321					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK,1322					UVD_DPG_PAUSE__NJ_PAUSE_DPG_ACK_MASK);1323 1324				SOC15_WAIT_ON_RREG(VCN, inst_idx, regUVD_POWER_STATUS,1325					UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,1326					UVD_POWER_STATUS__UVD_POWER_STATUS_MASK);1327			}1328		} else {1329			/* unpause dpg, no need to wait */1330			reg_data &= ~UVD_DPG_PAUSE__NJ_PAUSE_DPG_REQ_MASK;1331			WREG32_SOC15(VCN, inst_idx, regUVD_DPG_PAUSE, reg_data);1332		}1333		adev->vcn.inst[inst_idx].pause_state.fw_based = new_state->fw_based;1334	}1335 1336	return 0;1337}1338 1339/**1340 * vcn_v4_0_5_unified_ring_get_rptr - get unified read pointer1341 *1342 * @ring: amdgpu_ring pointer1343 *1344 * Returns the current hardware unified read pointer1345 */1346static uint64_t vcn_v4_0_5_unified_ring_get_rptr(struct amdgpu_ring *ring)1347{1348	struct amdgpu_device *adev = ring->adev;1349 1350	if (ring != &adev->vcn.inst[ring->me].ring_enc[0])1351		DRM_ERROR("wrong ring id is identified in %s", __func__);1352 1353	return RREG32_SOC15(VCN, ring->me, regUVD_RB_RPTR);1354}1355 1356/**1357 * vcn_v4_0_5_unified_ring_get_wptr - get unified write pointer1358 *1359 * @ring: amdgpu_ring pointer1360 *1361 * Returns the current hardware unified write pointer1362 */1363static uint64_t vcn_v4_0_5_unified_ring_get_wptr(struct amdgpu_ring *ring)1364{1365	struct amdgpu_device *adev = ring->adev;1366 1367	if (ring != &adev->vcn.inst[ring->me].ring_enc[0])1368		DRM_ERROR("wrong ring id is identified in %s", __func__);1369 1370	if (ring->use_doorbell)1371		return *ring->wptr_cpu_addr;1372	else1373		return RREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR);1374}1375 1376/**1377 * vcn_v4_0_5_unified_ring_set_wptr - set enc write pointer1378 *1379 * @ring: amdgpu_ring pointer1380 *1381 * Commits the enc write pointer to the hardware1382 */1383static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring)1384{1385	struct amdgpu_device *adev = ring->adev;1386 1387	if (ring != &adev->vcn.inst[ring->me].ring_enc[0])1388		DRM_ERROR("wrong ring id is identified in %s", __func__);1389 1390	if (ring->use_doorbell) {1391		*ring->wptr_cpu_addr = lower_32_bits(ring->wptr);1392		WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));1393	} else {1394		WREG32_SOC15(VCN, ring->me, regUVD_RB_WPTR, lower_32_bits(ring->wptr));1395	}1396}1397 1398static const struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {1399	.type = AMDGPU_RING_TYPE_VCN_ENC,1400	.align_mask = 0x3f,1401	.nop = VCN_ENC_CMD_NO_OP,1402	.get_rptr = vcn_v4_0_5_unified_ring_get_rptr,1403	.get_wptr = vcn_v4_0_5_unified_ring_get_wptr,1404	.set_wptr = vcn_v4_0_5_unified_ring_set_wptr,1405	.emit_frame_size =1406		SOC15_FLUSH_GPU_TLB_NUM_WREG * 3 +1407		SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 4 +1408		4 + /* vcn_v2_0_enc_ring_emit_vm_flush */1409		5 + 5 + /* vcn_v2_0_enc_ring_emit_fence x2 vm fence */1410		1, /* vcn_v2_0_enc_ring_insert_end */1411	.emit_ib_size = 5, /* vcn_v2_0_enc_ring_emit_ib */1412	.emit_ib = vcn_v2_0_enc_ring_emit_ib,1413	.emit_fence = vcn_v2_0_enc_ring_emit_fence,1414	.emit_vm_flush = vcn_v2_0_enc_ring_emit_vm_flush,1415	.test_ring = amdgpu_vcn_enc_ring_test_ring,1416	.test_ib = amdgpu_vcn_unified_ring_test_ib,1417	.insert_nop = amdgpu_ring_insert_nop,1418	.insert_end = vcn_v2_0_enc_ring_insert_end,1419	.pad_ib = amdgpu_ring_generic_pad_ib,1420	.begin_use = amdgpu_vcn_ring_begin_use,1421	.end_use = amdgpu_vcn_ring_end_use,1422	.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,1423	.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,1424	.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,1425};1426 1427/**1428 * vcn_v4_0_5_set_unified_ring_funcs - set unified ring functions1429 *1430 * @adev: amdgpu_device pointer1431 *1432 * Set unified ring functions1433 */1434static void vcn_v4_0_5_set_unified_ring_funcs(struct amdgpu_device *adev)1435{1436	int i;1437 1438	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1439		if (adev->vcn.harvest_config & (1 << i))1440			continue;1441 1442		adev->vcn.inst[i].ring_enc[0].funcs = &vcn_v4_0_5_unified_ring_vm_funcs;1443		adev->vcn.inst[i].ring_enc[0].me = i;1444	}1445}1446 1447/**1448 * vcn_v4_0_5_is_idle - check VCN block is idle1449 *1450 * @handle: amdgpu_device pointer1451 *1452 * Check whether VCN block is idle1453 */1454static bool vcn_v4_0_5_is_idle(void *handle)1455{1456	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1457	int i, ret = 1;1458 1459	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1460		if (adev->vcn.harvest_config & (1 << i))1461			continue;1462 1463		ret &= (RREG32_SOC15(VCN, i, regUVD_STATUS) == UVD_STATUS__IDLE);1464	}1465 1466	return ret;1467}1468 1469/**1470 * vcn_v4_0_5_wait_for_idle - wait for VCN block idle1471 *1472 * @handle: amdgpu_device pointer1473 *1474 * Wait for VCN block idle1475 */1476static int vcn_v4_0_5_wait_for_idle(void *handle)1477{1478	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1479	int i, ret = 0;1480 1481	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1482		if (adev->vcn.harvest_config & (1 << i))1483			continue;1484 1485		ret = SOC15_WAIT_ON_RREG(VCN, i, regUVD_STATUS, UVD_STATUS__IDLE,1486			UVD_STATUS__IDLE);1487		if (ret)1488			return ret;1489	}1490 1491	return ret;1492}1493 1494/**1495 * vcn_v4_0_5_set_clockgating_state - set VCN block clockgating state1496 *1497 * @handle: amdgpu_device pointer1498 * @state: clock gating state1499 *1500 * Set VCN block clockgating state1501 */1502static int vcn_v4_0_5_set_clockgating_state(void *handle, enum amd_clockgating_state state)1503{1504	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1505	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;1506	int i;1507 1508	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1509		if (adev->vcn.harvest_config & (1 << i))1510			continue;1511 1512		if (enable) {1513			if (RREG32_SOC15(VCN, i, regUVD_STATUS) != UVD_STATUS__IDLE)1514				return -EBUSY;1515			vcn_v4_0_5_enable_clock_gating(adev, i);1516		} else {1517			vcn_v4_0_5_disable_clock_gating(adev, i);1518		}1519	}1520 1521	return 0;1522}1523 1524/**1525 * vcn_v4_0_5_set_powergating_state - set VCN block powergating state1526 *1527 * @handle: amdgpu_device pointer1528 * @state: power gating state1529 *1530 * Set VCN block powergating state1531 */1532static int vcn_v4_0_5_set_powergating_state(void *handle, enum amd_powergating_state state)1533{1534	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1535	int ret;1536 1537	if (state == adev->vcn.cur_state)1538		return 0;1539 1540	if (state == AMD_PG_STATE_GATE)1541		ret = vcn_v4_0_5_stop(adev);1542	else1543		ret = vcn_v4_0_5_start(adev);1544 1545	if (!ret)1546		adev->vcn.cur_state = state;1547 1548	return ret;1549}1550 1551/**1552 * vcn_v4_0_5_process_interrupt - process VCN block interrupt1553 *1554 * @adev: amdgpu_device pointer1555 * @source: interrupt sources1556 * @entry: interrupt entry from clients and sources1557 *1558 * Process VCN block interrupt1559 */1560static int vcn_v4_0_5_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source,1561		struct amdgpu_iv_entry *entry)1562{1563	uint32_t ip_instance;1564 1565	switch (entry->client_id) {1566	case SOC15_IH_CLIENTID_VCN:1567		ip_instance = 0;1568		break;1569	case SOC15_IH_CLIENTID_VCN1:1570		ip_instance = 1;1571		break;1572	default:1573		DRM_ERROR("Unhandled client id: %d\n", entry->client_id);1574		return 0;1575	}1576 1577	DRM_DEBUG("IH: VCN TRAP\n");1578 1579	switch (entry->src_id) {1580	case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:1581		amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]);1582		break;1583	case VCN_4_0__SRCID_UVD_POISON:1584		amdgpu_vcn_process_poison_irq(adev, source, entry);1585		break;1586	default:1587		DRM_ERROR("Unhandled interrupt: %d %d\n",1588			  entry->src_id, entry->src_data[0]);1589		break;1590	}1591 1592	return 0;1593}1594 1595static const struct amdgpu_irq_src_funcs vcn_v4_0_5_irq_funcs = {1596	.process = vcn_v4_0_5_process_interrupt,1597};1598 1599/**1600 * vcn_v4_0_5_set_irq_funcs - set VCN block interrupt irq functions1601 *1602 * @adev: amdgpu_device pointer1603 *1604 * Set VCN block interrupt irq functions1605 */1606static void vcn_v4_0_5_set_irq_funcs(struct amdgpu_device *adev)1607{1608	int i;1609 1610	for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {1611		if (adev->vcn.harvest_config & (1 << i))1612			continue;1613 1614		adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1;1615		adev->vcn.inst[i].irq.funcs = &vcn_v4_0_5_irq_funcs;1616	}1617}1618 1619static void vcn_v4_0_5_print_ip_state(void *handle, struct drm_printer *p)1620{1621	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1622	int i, j;1623	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_5);1624	uint32_t inst_off, is_powered;1625 1626	if (!adev->vcn.ip_dump)1627		return;1628 1629	drm_printf(p, "num_instances:%d\n", adev->vcn.num_vcn_inst);1630	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {1631		if (adev->vcn.harvest_config & (1 << i)) {1632			drm_printf(p, "\nHarvested Instance:VCN%d Skipping dump\n", i);1633			continue;1634		}1635 1636		inst_off = i * reg_count;1637		is_powered = (adev->vcn.ip_dump[inst_off] &1638				UVD_POWER_STATUS__UVD_POWER_STATUS_MASK) != 1;1639 1640		if (is_powered) {1641			drm_printf(p, "\nActive Instance:VCN%d\n", i);1642			for (j = 0; j < reg_count; j++)1643				drm_printf(p, "%-50s \t 0x%08x\n", vcn_reg_list_4_0_5[j].reg_name,1644					   adev->vcn.ip_dump[inst_off + j]);1645		} else {1646			drm_printf(p, "\nInactive Instance:VCN%d\n", i);1647		}1648	}1649}1650 1651static void vcn_v4_0_5_dump_ip_state(void *handle)1652{1653	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1654	int i, j;1655	bool is_powered;1656	uint32_t inst_off;1657	uint32_t reg_count = ARRAY_SIZE(vcn_reg_list_4_0_5);1658 1659	if (!adev->vcn.ip_dump)1660		return;1661 1662	for (i = 0; i < adev->vcn.num_vcn_inst; i++) {1663		if (adev->vcn.harvest_config & (1 << i))1664			continue;1665 1666		inst_off = i * reg_count;1667		/* mmUVD_POWER_STATUS is always readable and is first element of the array */1668		adev->vcn.ip_dump[inst_off] = RREG32_SOC15(VCN, i, regUVD_POWER_STATUS);1669		is_powered = (adev->vcn.ip_dump[inst_off] &1670				UVD_POWER_STATUS__UVD_POWER_STATUS_MASK) != 1;1671 1672		if (is_powered)1673			for (j = 1; j < reg_count; j++)1674				adev->vcn.ip_dump[inst_off + j] =1675					RREG32(SOC15_REG_ENTRY_OFFSET_INST(vcn_reg_list_4_0_5[j],1676									   i));1677	}1678}1679 1680static const struct amd_ip_funcs vcn_v4_0_5_ip_funcs = {1681	.name = "vcn_v4_0_5",1682	.early_init = vcn_v4_0_5_early_init,1683	.late_init = NULL,1684	.sw_init = vcn_v4_0_5_sw_init,1685	.sw_fini = vcn_v4_0_5_sw_fini,1686	.hw_init = vcn_v4_0_5_hw_init,1687	.hw_fini = vcn_v4_0_5_hw_fini,1688	.suspend = vcn_v4_0_5_suspend,1689	.resume = vcn_v4_0_5_resume,1690	.is_idle = vcn_v4_0_5_is_idle,1691	.wait_for_idle = vcn_v4_0_5_wait_for_idle,1692	.check_soft_reset = NULL,1693	.pre_soft_reset = NULL,1694	.soft_reset = NULL,1695	.post_soft_reset = NULL,1696	.set_clockgating_state = vcn_v4_0_5_set_clockgating_state,1697	.set_powergating_state = vcn_v4_0_5_set_powergating_state,1698	.dump_ip_state = vcn_v4_0_5_dump_ip_state,1699	.print_ip_state = vcn_v4_0_5_print_ip_state,1700};1701 1702const struct amdgpu_ip_block_version vcn_v4_0_5_ip_block = {1703	.type = AMD_IP_BLOCK_TYPE_VCN,1704	.major = 4,1705	.minor = 0,1706	.rev = 5,1707	.funcs = &vcn_v4_0_5_ip_funcs,1708};1709