brintos

brintos / linux-shallow public Read only

0
0
Text · 44.7 KiB · 495de50 Raw
1696 lines · c
1/*2 * Copyright 2014 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 * Authors: Christian König <christian.koenig@amd.com>23 */24 25#include <linux/firmware.h>26 27#include "amdgpu.h"28#include "amdgpu_uvd.h"29#include "vid.h"30#include "uvd/uvd_6_0_d.h"31#include "uvd/uvd_6_0_sh_mask.h"32#include "oss/oss_2_0_d.h"33#include "oss/oss_2_0_sh_mask.h"34#include "smu/smu_7_1_3_d.h"35#include "smu/smu_7_1_3_sh_mask.h"36#include "bif/bif_5_1_d.h"37#include "gmc/gmc_8_1_d.h"38#include "vi.h"39#include "ivsrcid/ivsrcid_vislands30.h"40 41/* Polaris10/11/12 firmware version */42#define FW_1_130_16 ((1 << 24) | (130 << 16) | (16 << 8))43 44static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev);45static void uvd_v6_0_set_enc_ring_funcs(struct amdgpu_device *adev);46 47static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev);48static int uvd_v6_0_start(struct amdgpu_device *adev);49static void uvd_v6_0_stop(struct amdgpu_device *adev);50static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev);51static int uvd_v6_0_set_clockgating_state(void *handle,52					  enum amd_clockgating_state state);53static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev,54				 bool enable);55 56/**57* uvd_v6_0_enc_support - get encode support status58*59* @adev: amdgpu_device pointer60*61* Returns the current hardware encode support status62*/63static inline bool uvd_v6_0_enc_support(struct amdgpu_device *adev)64{65	return ((adev->asic_type >= CHIP_POLARIS10) &&66			(adev->asic_type <= CHIP_VEGAM) &&67			(!adev->uvd.fw_version || adev->uvd.fw_version >= FW_1_130_16));68}69 70/**71 * uvd_v6_0_ring_get_rptr - get read pointer72 *73 * @ring: amdgpu_ring pointer74 *75 * Returns the current hardware read pointer76 */77static uint64_t uvd_v6_0_ring_get_rptr(struct amdgpu_ring *ring)78{79	struct amdgpu_device *adev = ring->adev;80 81	return RREG32(mmUVD_RBC_RB_RPTR);82}83 84/**85 * uvd_v6_0_enc_ring_get_rptr - get enc read pointer86 *87 * @ring: amdgpu_ring pointer88 *89 * Returns the current hardware enc read pointer90 */91static uint64_t uvd_v6_0_enc_ring_get_rptr(struct amdgpu_ring *ring)92{93	struct amdgpu_device *adev = ring->adev;94 95	if (ring == &adev->uvd.inst->ring_enc[0])96		return RREG32(mmUVD_RB_RPTR);97	else98		return RREG32(mmUVD_RB_RPTR2);99}100/**101 * uvd_v6_0_ring_get_wptr - get write pointer102 *103 * @ring: amdgpu_ring pointer104 *105 * Returns the current hardware write pointer106 */107static uint64_t uvd_v6_0_ring_get_wptr(struct amdgpu_ring *ring)108{109	struct amdgpu_device *adev = ring->adev;110 111	return RREG32(mmUVD_RBC_RB_WPTR);112}113 114/**115 * uvd_v6_0_enc_ring_get_wptr - get enc write pointer116 *117 * @ring: amdgpu_ring pointer118 *119 * Returns the current hardware enc write pointer120 */121static uint64_t uvd_v6_0_enc_ring_get_wptr(struct amdgpu_ring *ring)122{123	struct amdgpu_device *adev = ring->adev;124 125	if (ring == &adev->uvd.inst->ring_enc[0])126		return RREG32(mmUVD_RB_WPTR);127	else128		return RREG32(mmUVD_RB_WPTR2);129}130 131/**132 * uvd_v6_0_ring_set_wptr - set write pointer133 *134 * @ring: amdgpu_ring pointer135 *136 * Commits the write pointer to the hardware137 */138static void uvd_v6_0_ring_set_wptr(struct amdgpu_ring *ring)139{140	struct amdgpu_device *adev = ring->adev;141 142	WREG32(mmUVD_RBC_RB_WPTR, lower_32_bits(ring->wptr));143}144 145/**146 * uvd_v6_0_enc_ring_set_wptr - set enc write pointer147 *148 * @ring: amdgpu_ring pointer149 *150 * Commits the enc write pointer to the hardware151 */152static void uvd_v6_0_enc_ring_set_wptr(struct amdgpu_ring *ring)153{154	struct amdgpu_device *adev = ring->adev;155 156	if (ring == &adev->uvd.inst->ring_enc[0])157		WREG32(mmUVD_RB_WPTR,158			lower_32_bits(ring->wptr));159	else160		WREG32(mmUVD_RB_WPTR2,161			lower_32_bits(ring->wptr));162}163 164/**165 * uvd_v6_0_enc_ring_test_ring - test if UVD ENC ring is working166 *167 * @ring: the engine to test on168 *169 */170static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring)171{172	struct amdgpu_device *adev = ring->adev;173	uint32_t rptr;174	unsigned i;175	int r;176 177	r = amdgpu_ring_alloc(ring, 16);178	if (r)179		return r;180 181	rptr = amdgpu_ring_get_rptr(ring);182 183	amdgpu_ring_write(ring, HEVC_ENC_CMD_END);184	amdgpu_ring_commit(ring);185 186	for (i = 0; i < adev->usec_timeout; i++) {187		if (amdgpu_ring_get_rptr(ring) != rptr)188			break;189		udelay(1);190	}191 192	if (i >= adev->usec_timeout)193		r = -ETIMEDOUT;194 195	return r;196}197 198/**199 * uvd_v6_0_enc_get_create_msg - generate a UVD ENC create msg200 *201 * @ring: ring we should submit the msg to202 * @handle: session handle to use203 * @bo: amdgpu object for which we query the offset204 * @fence: optional fence to return205 *206 * Open up a stream for HW test207 */208static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,209				       struct amdgpu_bo *bo,210				       struct dma_fence **fence)211{212	const unsigned ib_size_dw = 16;213	struct amdgpu_job *job;214	struct amdgpu_ib *ib;215	struct dma_fence *f = NULL;216	uint64_t addr;217	int i, r;218 219	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,220				     AMDGPU_IB_POOL_DIRECT, &job);221	if (r)222		return r;223 224	ib = &job->ibs[0];225	addr = amdgpu_bo_gpu_offset(bo);226 227	ib->length_dw = 0;228	ib->ptr[ib->length_dw++] = 0x00000018;229	ib->ptr[ib->length_dw++] = 0x00000001; /* session info */230	ib->ptr[ib->length_dw++] = handle;231	ib->ptr[ib->length_dw++] = 0x00010000;232	ib->ptr[ib->length_dw++] = upper_32_bits(addr);233	ib->ptr[ib->length_dw++] = addr;234 235	ib->ptr[ib->length_dw++] = 0x00000014;236	ib->ptr[ib->length_dw++] = 0x00000002; /* task info */237	ib->ptr[ib->length_dw++] = 0x0000001c;238	ib->ptr[ib->length_dw++] = 0x00000001;239	ib->ptr[ib->length_dw++] = 0x00000000;240 241	ib->ptr[ib->length_dw++] = 0x00000008;242	ib->ptr[ib->length_dw++] = 0x08000001; /* op initialize */243 244	for (i = ib->length_dw; i < ib_size_dw; ++i)245		ib->ptr[i] = 0x0;246 247	r = amdgpu_job_submit_direct(job, ring, &f);248	if (r)249		goto err;250 251	if (fence)252		*fence = dma_fence_get(f);253	dma_fence_put(f);254	return 0;255 256err:257	amdgpu_job_free(job);258	return r;259}260 261/**262 * uvd_v6_0_enc_get_destroy_msg - generate a UVD ENC destroy msg263 *264 * @ring: ring we should submit the msg to265 * @handle: session handle to use266 * @bo: amdgpu object for which we query the offset267 * @fence: optional fence to return268 *269 * Close up a stream for HW test or if userspace failed to do so270 */271static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,272					uint32_t handle,273					struct amdgpu_bo *bo,274					struct dma_fence **fence)275{276	const unsigned ib_size_dw = 16;277	struct amdgpu_job *job;278	struct amdgpu_ib *ib;279	struct dma_fence *f = NULL;280	uint64_t addr;281	int i, r;282 283	r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,284				     AMDGPU_IB_POOL_DIRECT, &job);285	if (r)286		return r;287 288	ib = &job->ibs[0];289	addr = amdgpu_bo_gpu_offset(bo);290 291	ib->length_dw = 0;292	ib->ptr[ib->length_dw++] = 0x00000018;293	ib->ptr[ib->length_dw++] = 0x00000001; /* session info */294	ib->ptr[ib->length_dw++] = handle;295	ib->ptr[ib->length_dw++] = 0x00010000;296	ib->ptr[ib->length_dw++] = upper_32_bits(addr);297	ib->ptr[ib->length_dw++] = addr;298 299	ib->ptr[ib->length_dw++] = 0x00000014;300	ib->ptr[ib->length_dw++] = 0x00000002; /* task info */301	ib->ptr[ib->length_dw++] = 0x0000001c;302	ib->ptr[ib->length_dw++] = 0x00000001;303	ib->ptr[ib->length_dw++] = 0x00000000;304 305	ib->ptr[ib->length_dw++] = 0x00000008;306	ib->ptr[ib->length_dw++] = 0x08000002; /* op close session */307 308	for (i = ib->length_dw; i < ib_size_dw; ++i)309		ib->ptr[i] = 0x0;310 311	r = amdgpu_job_submit_direct(job, ring, &f);312	if (r)313		goto err;314 315	if (fence)316		*fence = dma_fence_get(f);317	dma_fence_put(f);318	return 0;319 320err:321	amdgpu_job_free(job);322	return r;323}324 325/**326 * uvd_v6_0_enc_ring_test_ib - test if UVD ENC IBs are working327 *328 * @ring: the engine to test on329 * @timeout: timeout value in jiffies, or MAX_SCHEDULE_TIMEOUT330 *331 */332static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)333{334	struct dma_fence *fence = NULL;335	struct amdgpu_bo *bo = ring->adev->uvd.ib_bo;336	long r;337 338	r = uvd_v6_0_enc_get_create_msg(ring, 1, bo, NULL);339	if (r)340		goto error;341 342	r = uvd_v6_0_enc_get_destroy_msg(ring, 1, bo, &fence);343	if (r)344		goto error;345 346	r = dma_fence_wait_timeout(fence, false, timeout);347	if (r == 0)348		r = -ETIMEDOUT;349	else if (r > 0)350		r = 0;351 352error:353	dma_fence_put(fence);354	return r;355}356 357static int uvd_v6_0_early_init(void *handle)358{359	struct amdgpu_device *adev = (struct amdgpu_device *)handle;360	adev->uvd.num_uvd_inst = 1;361 362	if (!(adev->flags & AMD_IS_APU) &&363	    (RREG32_SMC(ixCC_HARVEST_FUSES) & CC_HARVEST_FUSES__UVD_DISABLE_MASK))364		return -ENOENT;365 366	uvd_v6_0_set_ring_funcs(adev);367 368	if (uvd_v6_0_enc_support(adev)) {369		adev->uvd.num_enc_rings = 2;370		uvd_v6_0_set_enc_ring_funcs(adev);371	}372 373	uvd_v6_0_set_irq_funcs(adev);374 375	return 0;376}377 378static int uvd_v6_0_sw_init(void *handle)379{380	struct amdgpu_ring *ring;381	int i, r;382	struct amdgpu_device *adev = (struct amdgpu_device *)handle;383 384	/* UVD TRAP */385	r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_UVD_SYSTEM_MESSAGE, &adev->uvd.inst->irq);386	if (r)387		return r;388 389	/* UVD ENC TRAP */390	if (uvd_v6_0_enc_support(adev)) {391		for (i = 0; i < adev->uvd.num_enc_rings; ++i) {392			r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, i + VISLANDS30_IV_SRCID_UVD_ENC_GEN_PURP, &adev->uvd.inst->irq);393			if (r)394				return r;395		}396	}397 398	r = amdgpu_uvd_sw_init(adev);399	if (r)400		return r;401 402	if (!uvd_v6_0_enc_support(adev)) {403		for (i = 0; i < adev->uvd.num_enc_rings; ++i)404			adev->uvd.inst->ring_enc[i].funcs = NULL;405 406		adev->uvd.inst->irq.num_types = 1;407		adev->uvd.num_enc_rings = 0;408 409		DRM_INFO("UVD ENC is disabled\n");410	}411 412	ring = &adev->uvd.inst->ring;413	sprintf(ring->name, "uvd");414	r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.inst->irq, 0,415			     AMDGPU_RING_PRIO_DEFAULT, NULL);416	if (r)417		return r;418 419	r = amdgpu_uvd_resume(adev);420	if (r)421		return r;422 423	if (uvd_v6_0_enc_support(adev)) {424		for (i = 0; i < adev->uvd.num_enc_rings; ++i) {425			ring = &adev->uvd.inst->ring_enc[i];426			sprintf(ring->name, "uvd_enc%d", i);427			r = amdgpu_ring_init(adev, ring, 512,428					     &adev->uvd.inst->irq, 0,429					     AMDGPU_RING_PRIO_DEFAULT, NULL);430			if (r)431				return r;432		}433	}434 435	return r;436}437 438static int uvd_v6_0_sw_fini(void *handle)439{440	int i, r;441	struct amdgpu_device *adev = (struct amdgpu_device *)handle;442 443	r = amdgpu_uvd_suspend(adev);444	if (r)445		return r;446 447	if (uvd_v6_0_enc_support(adev)) {448		for (i = 0; i < adev->uvd.num_enc_rings; ++i)449			amdgpu_ring_fini(&adev->uvd.inst->ring_enc[i]);450	}451 452	return amdgpu_uvd_sw_fini(adev);453}454 455/**456 * uvd_v6_0_hw_init - start and test UVD block457 *458 * @handle: handle used to pass amdgpu_device pointer459 *460 * Initialize the hardware, boot up the VCPU and do some testing461 */462static int uvd_v6_0_hw_init(void *handle)463{464	struct amdgpu_device *adev = (struct amdgpu_device *)handle;465	struct amdgpu_ring *ring = &adev->uvd.inst->ring;466	uint32_t tmp;467	int i, r;468 469	amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);470	uvd_v6_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);471	uvd_v6_0_enable_mgcg(adev, true);472 473	r = amdgpu_ring_test_helper(ring);474	if (r)475		goto done;476 477	r = amdgpu_ring_alloc(ring, 10);478	if (r) {479		DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r);480		goto done;481	}482 483	tmp = PACKET0(mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL, 0);484	amdgpu_ring_write(ring, tmp);485	amdgpu_ring_write(ring, 0xFFFFF);486 487	tmp = PACKET0(mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL, 0);488	amdgpu_ring_write(ring, tmp);489	amdgpu_ring_write(ring, 0xFFFFF);490 491	tmp = PACKET0(mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL, 0);492	amdgpu_ring_write(ring, tmp);493	amdgpu_ring_write(ring, 0xFFFFF);494 495	/* Clear timeout status bits */496	amdgpu_ring_write(ring, PACKET0(mmUVD_SEMA_TIMEOUT_STATUS, 0));497	amdgpu_ring_write(ring, 0x8);498 499	amdgpu_ring_write(ring, PACKET0(mmUVD_SEMA_CNTL, 0));500	amdgpu_ring_write(ring, 3);501 502	amdgpu_ring_commit(ring);503 504	if (uvd_v6_0_enc_support(adev)) {505		for (i = 0; i < adev->uvd.num_enc_rings; ++i) {506			ring = &adev->uvd.inst->ring_enc[i];507			r = amdgpu_ring_test_helper(ring);508			if (r)509				goto done;510		}511	}512 513done:514	if (!r) {515		if (uvd_v6_0_enc_support(adev))516			DRM_INFO("UVD and UVD ENC initialized successfully.\n");517		else518			DRM_INFO("UVD initialized successfully.\n");519	}520 521	return r;522}523 524/**525 * uvd_v6_0_hw_fini - stop the hardware block526 *527 * @handle: handle used to pass amdgpu_device pointer528 *529 * Stop the UVD block, mark ring as not ready any more530 */531static int uvd_v6_0_hw_fini(void *handle)532{533	struct amdgpu_device *adev = (struct amdgpu_device *)handle;534 535	cancel_delayed_work_sync(&adev->uvd.idle_work);536 537	if (RREG32(mmUVD_STATUS) != 0)538		uvd_v6_0_stop(adev);539 540	return 0;541}542 543static int uvd_v6_0_prepare_suspend(void *handle)544{545	struct amdgpu_device *adev = (struct amdgpu_device *)handle;546 547	return amdgpu_uvd_prepare_suspend(adev);548}549 550static int uvd_v6_0_suspend(void *handle)551{552	int r;553	struct amdgpu_device *adev = (struct amdgpu_device *)handle;554 555	/*556	 * Proper cleanups before halting the HW engine:557	 *   - cancel the delayed idle work558	 *   - enable powergating559	 *   - enable clockgating560	 *   - disable dpm561	 *562	 * TODO: to align with the VCN implementation, move the563	 * jobs for clockgating/powergating/dpm setting to564	 * ->set_powergating_state().565	 */566	cancel_delayed_work_sync(&adev->uvd.idle_work);567 568	if (adev->pm.dpm_enabled) {569		amdgpu_dpm_enable_uvd(adev, false);570	} else {571		amdgpu_asic_set_uvd_clocks(adev, 0, 0);572		/* shutdown the UVD block */573		amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,574						       AMD_PG_STATE_GATE);575		amdgpu_device_ip_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,576						       AMD_CG_STATE_GATE);577	}578 579	r = uvd_v6_0_hw_fini(adev);580	if (r)581		return r;582 583	return amdgpu_uvd_suspend(adev);584}585 586static int uvd_v6_0_resume(void *handle)587{588	int r;589	struct amdgpu_device *adev = (struct amdgpu_device *)handle;590 591	r = amdgpu_uvd_resume(adev);592	if (r)593		return r;594 595	return uvd_v6_0_hw_init(adev);596}597 598/**599 * uvd_v6_0_mc_resume - memory controller programming600 *601 * @adev: amdgpu_device pointer602 *603 * Let the UVD memory controller know it's offsets604 */605static void uvd_v6_0_mc_resume(struct amdgpu_device *adev)606{607	uint64_t offset;608	uint32_t size;609 610	/* program memory controller bits 0-27 */611	WREG32(mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,612			lower_32_bits(adev->uvd.inst->gpu_addr));613	WREG32(mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH,614			upper_32_bits(adev->uvd.inst->gpu_addr));615 616	offset = AMDGPU_UVD_FIRMWARE_OFFSET;617	size = AMDGPU_UVD_FIRMWARE_SIZE(adev);618	WREG32(mmUVD_VCPU_CACHE_OFFSET0, offset >> 3);619	WREG32(mmUVD_VCPU_CACHE_SIZE0, size);620 621	offset += size;622	size = AMDGPU_UVD_HEAP_SIZE;623	WREG32(mmUVD_VCPU_CACHE_OFFSET1, offset >> 3);624	WREG32(mmUVD_VCPU_CACHE_SIZE1, size);625 626	offset += size;627	size = AMDGPU_UVD_STACK_SIZE +628	       (AMDGPU_UVD_SESSION_SIZE * adev->uvd.max_handles);629	WREG32(mmUVD_VCPU_CACHE_OFFSET2, offset >> 3);630	WREG32(mmUVD_VCPU_CACHE_SIZE2, size);631 632	WREG32(mmUVD_UDEC_ADDR_CONFIG, adev->gfx.config.gb_addr_config);633	WREG32(mmUVD_UDEC_DB_ADDR_CONFIG, adev->gfx.config.gb_addr_config);634	WREG32(mmUVD_UDEC_DBW_ADDR_CONFIG, adev->gfx.config.gb_addr_config);635 636	WREG32(mmUVD_GP_SCRATCH4, adev->uvd.max_handles);637}638 639#if 0640static void cz_set_uvd_clock_gating_branches(struct amdgpu_device *adev,641		bool enable)642{643	u32 data, data1;644 645	data = RREG32(mmUVD_CGC_GATE);646	data1 = RREG32(mmUVD_SUVD_CGC_GATE);647	if (enable) {648		data |= UVD_CGC_GATE__SYS_MASK |649				UVD_CGC_GATE__UDEC_MASK |650				UVD_CGC_GATE__MPEG2_MASK |651				UVD_CGC_GATE__RBC_MASK |652				UVD_CGC_GATE__LMI_MC_MASK |653				UVD_CGC_GATE__IDCT_MASK |654				UVD_CGC_GATE__MPRD_MASK |655				UVD_CGC_GATE__MPC_MASK |656				UVD_CGC_GATE__LBSI_MASK |657				UVD_CGC_GATE__LRBBM_MASK |658				UVD_CGC_GATE__UDEC_RE_MASK |659				UVD_CGC_GATE__UDEC_CM_MASK |660				UVD_CGC_GATE__UDEC_IT_MASK |661				UVD_CGC_GATE__UDEC_DB_MASK |662				UVD_CGC_GATE__UDEC_MP_MASK |663				UVD_CGC_GATE__WCB_MASK |664				UVD_CGC_GATE__VCPU_MASK |665				UVD_CGC_GATE__SCPU_MASK;666		data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |667				UVD_SUVD_CGC_GATE__SIT_MASK |668				UVD_SUVD_CGC_GATE__SMP_MASK |669				UVD_SUVD_CGC_GATE__SCM_MASK |670				UVD_SUVD_CGC_GATE__SDB_MASK |671				UVD_SUVD_CGC_GATE__SRE_H264_MASK |672				UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |673				UVD_SUVD_CGC_GATE__SIT_H264_MASK |674				UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |675				UVD_SUVD_CGC_GATE__SCM_H264_MASK |676				UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |677				UVD_SUVD_CGC_GATE__SDB_H264_MASK |678				UVD_SUVD_CGC_GATE__SDB_HEVC_MASK;679	} else {680		data &= ~(UVD_CGC_GATE__SYS_MASK |681				UVD_CGC_GATE__UDEC_MASK |682				UVD_CGC_GATE__MPEG2_MASK |683				UVD_CGC_GATE__RBC_MASK |684				UVD_CGC_GATE__LMI_MC_MASK |685				UVD_CGC_GATE__LMI_UMC_MASK |686				UVD_CGC_GATE__IDCT_MASK |687				UVD_CGC_GATE__MPRD_MASK |688				UVD_CGC_GATE__MPC_MASK |689				UVD_CGC_GATE__LBSI_MASK |690				UVD_CGC_GATE__LRBBM_MASK |691				UVD_CGC_GATE__UDEC_RE_MASK |692				UVD_CGC_GATE__UDEC_CM_MASK |693				UVD_CGC_GATE__UDEC_IT_MASK |694				UVD_CGC_GATE__UDEC_DB_MASK |695				UVD_CGC_GATE__UDEC_MP_MASK |696				UVD_CGC_GATE__WCB_MASK |697				UVD_CGC_GATE__VCPU_MASK |698				UVD_CGC_GATE__SCPU_MASK);699		data1 &= ~(UVD_SUVD_CGC_GATE__SRE_MASK |700				UVD_SUVD_CGC_GATE__SIT_MASK |701				UVD_SUVD_CGC_GATE__SMP_MASK |702				UVD_SUVD_CGC_GATE__SCM_MASK |703				UVD_SUVD_CGC_GATE__SDB_MASK |704				UVD_SUVD_CGC_GATE__SRE_H264_MASK |705				UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |706				UVD_SUVD_CGC_GATE__SIT_H264_MASK |707				UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |708				UVD_SUVD_CGC_GATE__SCM_H264_MASK |709				UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |710				UVD_SUVD_CGC_GATE__SDB_H264_MASK |711				UVD_SUVD_CGC_GATE__SDB_HEVC_MASK);712	}713	WREG32(mmUVD_CGC_GATE, data);714	WREG32(mmUVD_SUVD_CGC_GATE, data1);715}716#endif717 718/**719 * uvd_v6_0_start - start UVD block720 *721 * @adev: amdgpu_device pointer722 *723 * Setup and start the UVD block724 */725static int uvd_v6_0_start(struct amdgpu_device *adev)726{727	struct amdgpu_ring *ring = &adev->uvd.inst->ring;728	uint32_t rb_bufsz, tmp;729	uint32_t lmi_swap_cntl;730	uint32_t mp_swap_cntl;731	int i, j, r;732 733	/* disable DPG */734	WREG32_P(mmUVD_POWER_STATUS, 0, ~UVD_POWER_STATUS__UVD_PG_MODE_MASK);735 736	/* disable byte swapping */737	lmi_swap_cntl = 0;738	mp_swap_cntl = 0;739 740	uvd_v6_0_mc_resume(adev);741 742	/* disable interupt */743	WREG32_FIELD(UVD_MASTINT_EN, VCPU_EN, 0);744 745	/* stall UMC and register bus before resetting VCPU */746	WREG32_FIELD(UVD_LMI_CTRL2, STALL_ARB_UMC, 1);747	mdelay(1);748 749	/* put LMI, VCPU, RBC etc... into reset */750	WREG32(mmUVD_SOFT_RESET,751		UVD_SOFT_RESET__LMI_SOFT_RESET_MASK |752		UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK |753		UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK |754		UVD_SOFT_RESET__RBC_SOFT_RESET_MASK |755		UVD_SOFT_RESET__CSM_SOFT_RESET_MASK |756		UVD_SOFT_RESET__CXW_SOFT_RESET_MASK |757		UVD_SOFT_RESET__TAP_SOFT_RESET_MASK |758		UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK);759	mdelay(5);760 761	/* take UVD block out of reset */762	WREG32_FIELD(SRBM_SOFT_RESET, SOFT_RESET_UVD, 0);763	mdelay(5);764 765	/* initialize UVD memory controller */766	WREG32(mmUVD_LMI_CTRL,767		(0x40 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |768		UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |769		UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |770		UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |771		UVD_LMI_CTRL__REQ_MODE_MASK |772		UVD_LMI_CTRL__DISABLE_ON_FWV_FAIL_MASK);773 774#ifdef __BIG_ENDIAN775	/* swap (8 in 32) RB and IB */776	lmi_swap_cntl = 0xa;777	mp_swap_cntl = 0;778#endif779	WREG32(mmUVD_LMI_SWAP_CNTL, lmi_swap_cntl);780	WREG32(mmUVD_MP_SWAP_CNTL, mp_swap_cntl);781 782	WREG32(mmUVD_MPC_SET_MUXA0, 0x40c2040);783	WREG32(mmUVD_MPC_SET_MUXA1, 0x0);784	WREG32(mmUVD_MPC_SET_MUXB0, 0x40c2040);785	WREG32(mmUVD_MPC_SET_MUXB1, 0x0);786	WREG32(mmUVD_MPC_SET_ALU, 0);787	WREG32(mmUVD_MPC_SET_MUX, 0x88);788 789	/* take all subblocks out of reset, except VCPU */790	WREG32(mmUVD_SOFT_RESET, UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);791	mdelay(5);792 793	/* enable VCPU clock */794	WREG32(mmUVD_VCPU_CNTL, UVD_VCPU_CNTL__CLK_EN_MASK);795 796	/* enable UMC */797	WREG32_FIELD(UVD_LMI_CTRL2, STALL_ARB_UMC, 0);798 799	/* boot up the VCPU */800	WREG32(mmUVD_SOFT_RESET, 0);801	mdelay(10);802 803	for (i = 0; i < 10; ++i) {804		uint32_t status;805 806		for (j = 0; j < 100; ++j) {807			status = RREG32(mmUVD_STATUS);808			if (status & 2)809				break;810			mdelay(10);811		}812		r = 0;813		if (status & 2)814			break;815 816		DRM_ERROR("UVD not responding, trying to reset the VCPU!!!\n");817		WREG32_FIELD(UVD_SOFT_RESET, VCPU_SOFT_RESET, 1);818		mdelay(10);819		WREG32_FIELD(UVD_SOFT_RESET, VCPU_SOFT_RESET, 0);820		mdelay(10);821		r = -1;822	}823 824	if (r) {825		DRM_ERROR("UVD not responding, giving up!!!\n");826		return r;827	}828	/* enable master interrupt */829	WREG32_P(mmUVD_MASTINT_EN,830		(UVD_MASTINT_EN__VCPU_EN_MASK|UVD_MASTINT_EN__SYS_EN_MASK),831		~(UVD_MASTINT_EN__VCPU_EN_MASK|UVD_MASTINT_EN__SYS_EN_MASK));832 833	/* clear the bit 4 of UVD_STATUS */834	WREG32_P(mmUVD_STATUS, 0, ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT));835 836	/* force RBC into idle state */837	rb_bufsz = order_base_2(ring->ring_size);838	tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, rb_bufsz);839	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);840	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);841	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_WPTR_POLL_EN, 0);842	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);843	tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);844	WREG32(mmUVD_RBC_RB_CNTL, tmp);845 846	/* set the write pointer delay */847	WREG32(mmUVD_RBC_RB_WPTR_CNTL, 0);848 849	/* set the wb address */850	WREG32(mmUVD_RBC_RB_RPTR_ADDR, (upper_32_bits(ring->gpu_addr) >> 2));851 852	/* program the RB_BASE for ring buffer */853	WREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_LOW,854			lower_32_bits(ring->gpu_addr));855	WREG32(mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH,856			upper_32_bits(ring->gpu_addr));857 858	/* Initialize the ring buffer's read and write pointers */859	WREG32(mmUVD_RBC_RB_RPTR, 0);860 861	ring->wptr = RREG32(mmUVD_RBC_RB_RPTR);862	WREG32(mmUVD_RBC_RB_WPTR, lower_32_bits(ring->wptr));863 864	WREG32_FIELD(UVD_RBC_RB_CNTL, RB_NO_FETCH, 0);865 866	if (uvd_v6_0_enc_support(adev)) {867		ring = &adev->uvd.inst->ring_enc[0];868		WREG32(mmUVD_RB_RPTR, lower_32_bits(ring->wptr));869		WREG32(mmUVD_RB_WPTR, lower_32_bits(ring->wptr));870		WREG32(mmUVD_RB_BASE_LO, ring->gpu_addr);871		WREG32(mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr));872		WREG32(mmUVD_RB_SIZE, ring->ring_size / 4);873 874		ring = &adev->uvd.inst->ring_enc[1];875		WREG32(mmUVD_RB_RPTR2, lower_32_bits(ring->wptr));876		WREG32(mmUVD_RB_WPTR2, lower_32_bits(ring->wptr));877		WREG32(mmUVD_RB_BASE_LO2, ring->gpu_addr);878		WREG32(mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));879		WREG32(mmUVD_RB_SIZE2, ring->ring_size / 4);880	}881 882	return 0;883}884 885/**886 * uvd_v6_0_stop - stop UVD block887 *888 * @adev: amdgpu_device pointer889 *890 * stop the UVD block891 */892static void uvd_v6_0_stop(struct amdgpu_device *adev)893{894	/* force RBC into idle state */895	WREG32(mmUVD_RBC_RB_CNTL, 0x11010101);896 897	/* Stall UMC and register bus before resetting VCPU */898	WREG32_P(mmUVD_LMI_CTRL2, 1 << 8, ~(1 << 8));899	mdelay(1);900 901	/* put VCPU into reset */902	WREG32(mmUVD_SOFT_RESET, UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);903	mdelay(5);904 905	/* disable VCPU clock */906	WREG32(mmUVD_VCPU_CNTL, 0x0);907 908	/* Unstall UMC and register bus */909	WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));910 911	WREG32(mmUVD_STATUS, 0);912}913 914/**915 * uvd_v6_0_ring_emit_fence - emit an fence & trap command916 *917 * @ring: amdgpu_ring pointer918 * @addr: address919 * @seq: sequence number920 * @flags: fence related flags921 *922 * Write a fence and a trap command to the ring.923 */924static void uvd_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,925				     unsigned flags)926{927	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);928 929	amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0));930	amdgpu_ring_write(ring, seq);931	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0));932	amdgpu_ring_write(ring, addr & 0xffffffff);933	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0));934	amdgpu_ring_write(ring, upper_32_bits(addr) & 0xff);935	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0));936	amdgpu_ring_write(ring, 0);937 938	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0));939	amdgpu_ring_write(ring, 0);940	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0));941	amdgpu_ring_write(ring, 0);942	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0));943	amdgpu_ring_write(ring, 2);944}945 946/**947 * uvd_v6_0_enc_ring_emit_fence - emit an enc fence & trap command948 *949 * @ring: amdgpu_ring pointer950 * @addr: address951 * @seq: sequence number952 * @flags: fence related flags953 *954 * Write enc a fence and a trap command to the ring.955 */956static void uvd_v6_0_enc_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,957			u64 seq, unsigned flags)958{959	WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);960 961	amdgpu_ring_write(ring, HEVC_ENC_CMD_FENCE);962	amdgpu_ring_write(ring, addr);963	amdgpu_ring_write(ring, upper_32_bits(addr));964	amdgpu_ring_write(ring, seq);965	amdgpu_ring_write(ring, HEVC_ENC_CMD_TRAP);966}967 968/**969 * uvd_v6_0_ring_emit_hdp_flush - skip HDP flushing970 *971 * @ring: amdgpu_ring pointer972 */973static void uvd_v6_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)974{975	/* The firmware doesn't seem to like touching registers at this point. */976}977 978/**979 * uvd_v6_0_ring_test_ring - register write test980 *981 * @ring: amdgpu_ring pointer982 *983 * Test if we can successfully write to the context register984 */985static int uvd_v6_0_ring_test_ring(struct amdgpu_ring *ring)986{987	struct amdgpu_device *adev = ring->adev;988	uint32_t tmp = 0;989	unsigned i;990	int r;991 992	WREG32(mmUVD_CONTEXT_ID, 0xCAFEDEAD);993	r = amdgpu_ring_alloc(ring, 3);994	if (r)995		return r;996 997	amdgpu_ring_write(ring, PACKET0(mmUVD_CONTEXT_ID, 0));998	amdgpu_ring_write(ring, 0xDEADBEEF);999	amdgpu_ring_commit(ring);1000	for (i = 0; i < adev->usec_timeout; i++) {1001		tmp = RREG32(mmUVD_CONTEXT_ID);1002		if (tmp == 0xDEADBEEF)1003			break;1004		udelay(1);1005	}1006 1007	if (i >= adev->usec_timeout)1008		r = -ETIMEDOUT;1009 1010	return r;1011}1012 1013/**1014 * uvd_v6_0_ring_emit_ib - execute indirect buffer1015 *1016 * @ring: amdgpu_ring pointer1017 * @job: job to retrieve vmid from1018 * @ib: indirect buffer to execute1019 * @flags: unused1020 *1021 * Write ring commands to execute the indirect buffer1022 */1023static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring,1024				  struct amdgpu_job *job,1025				  struct amdgpu_ib *ib,1026				  uint32_t flags)1027{1028	unsigned vmid = AMDGPU_JOB_GET_VMID(job);1029 1030	amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_VMID, 0));1031	amdgpu_ring_write(ring, vmid);1032 1033	amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_LOW, 0));1034	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));1035	amdgpu_ring_write(ring, PACKET0(mmUVD_LMI_RBC_IB_64BIT_BAR_HIGH, 0));1036	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));1037	amdgpu_ring_write(ring, PACKET0(mmUVD_RBC_IB_SIZE, 0));1038	amdgpu_ring_write(ring, ib->length_dw);1039}1040 1041/**1042 * uvd_v6_0_enc_ring_emit_ib - enc execute indirect buffer1043 *1044 * @ring: amdgpu_ring pointer1045 * @job: job to retrive vmid from1046 * @ib: indirect buffer to execute1047 * @flags: unused1048 *1049 * Write enc ring commands to execute the indirect buffer1050 */1051static void uvd_v6_0_enc_ring_emit_ib(struct amdgpu_ring *ring,1052					struct amdgpu_job *job,1053					struct amdgpu_ib *ib,1054					uint32_t flags)1055{1056	unsigned vmid = AMDGPU_JOB_GET_VMID(job);1057 1058	amdgpu_ring_write(ring, HEVC_ENC_CMD_IB_VM);1059	amdgpu_ring_write(ring, vmid);1060	amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr));1061	amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));1062	amdgpu_ring_write(ring, ib->length_dw);1063}1064 1065static void uvd_v6_0_ring_emit_wreg(struct amdgpu_ring *ring,1066				    uint32_t reg, uint32_t val)1067{1068	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0));1069	amdgpu_ring_write(ring, reg << 2);1070	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0));1071	amdgpu_ring_write(ring, val);1072	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0));1073	amdgpu_ring_write(ring, 0x8);1074}1075 1076static void uvd_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring,1077					unsigned vmid, uint64_t pd_addr)1078{1079	amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);1080 1081	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0));1082	amdgpu_ring_write(ring, mmVM_INVALIDATE_REQUEST << 2);1083	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0));1084	amdgpu_ring_write(ring, 0);1085	amdgpu_ring_write(ring, PACKET0(mmUVD_GP_SCRATCH8, 0));1086	amdgpu_ring_write(ring, 1 << vmid); /* mask */1087	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0));1088	amdgpu_ring_write(ring, 0xC);1089}1090 1091static void uvd_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)1092{1093	uint32_t seq = ring->fence_drv.sync_seq;1094	uint64_t addr = ring->fence_drv.gpu_addr;1095 1096	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA0, 0));1097	amdgpu_ring_write(ring, lower_32_bits(addr));1098	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_DATA1, 0));1099	amdgpu_ring_write(ring, upper_32_bits(addr));1100	amdgpu_ring_write(ring, PACKET0(mmUVD_GP_SCRATCH8, 0));1101	amdgpu_ring_write(ring, 0xffffffff); /* mask */1102	amdgpu_ring_write(ring, PACKET0(mmUVD_GP_SCRATCH9, 0));1103	amdgpu_ring_write(ring, seq);1104	amdgpu_ring_write(ring, PACKET0(mmUVD_GPCOM_VCPU_CMD, 0));1105	amdgpu_ring_write(ring, 0xE);1106}1107 1108static void uvd_v6_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)1109{1110	int i;1111 1112	WARN_ON(ring->wptr % 2 || count % 2);1113 1114	for (i = 0; i < count / 2; i++) {1115		amdgpu_ring_write(ring, PACKET0(mmUVD_NO_OP, 0));1116		amdgpu_ring_write(ring, 0);1117	}1118}1119 1120static void uvd_v6_0_enc_ring_emit_pipeline_sync(struct amdgpu_ring *ring)1121{1122	uint32_t seq = ring->fence_drv.sync_seq;1123	uint64_t addr = ring->fence_drv.gpu_addr;1124 1125	amdgpu_ring_write(ring, HEVC_ENC_CMD_WAIT_GE);1126	amdgpu_ring_write(ring, lower_32_bits(addr));1127	amdgpu_ring_write(ring, upper_32_bits(addr));1128	amdgpu_ring_write(ring, seq);1129}1130 1131static void uvd_v6_0_enc_ring_insert_end(struct amdgpu_ring *ring)1132{1133	amdgpu_ring_write(ring, HEVC_ENC_CMD_END);1134}1135 1136static void uvd_v6_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring,1137					    unsigned int vmid, uint64_t pd_addr)1138{1139	amdgpu_ring_write(ring, HEVC_ENC_CMD_UPDATE_PTB);1140	amdgpu_ring_write(ring, vmid);1141	amdgpu_ring_write(ring, pd_addr >> 12);1142 1143	amdgpu_ring_write(ring, HEVC_ENC_CMD_FLUSH_TLB);1144	amdgpu_ring_write(ring, vmid);1145}1146 1147static bool uvd_v6_0_is_idle(void *handle)1148{1149	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1150 1151	return !(RREG32(mmSRBM_STATUS) & SRBM_STATUS__UVD_BUSY_MASK);1152}1153 1154static int uvd_v6_0_wait_for_idle(void *handle)1155{1156	unsigned i;1157	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1158 1159	for (i = 0; i < adev->usec_timeout; i++) {1160		if (uvd_v6_0_is_idle(handle))1161			return 0;1162	}1163	return -ETIMEDOUT;1164}1165 1166#define AMDGPU_UVD_STATUS_BUSY_MASK    0xfd1167static bool uvd_v6_0_check_soft_reset(void *handle)1168{1169	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1170	u32 srbm_soft_reset = 0;1171	u32 tmp = RREG32(mmSRBM_STATUS);1172 1173	if (REG_GET_FIELD(tmp, SRBM_STATUS, UVD_RQ_PENDING) ||1174	    REG_GET_FIELD(tmp, SRBM_STATUS, UVD_BUSY) ||1175	    (RREG32(mmUVD_STATUS) & AMDGPU_UVD_STATUS_BUSY_MASK))1176		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_UVD, 1);1177 1178	if (srbm_soft_reset) {1179		adev->uvd.inst->srbm_soft_reset = srbm_soft_reset;1180		return true;1181	} else {1182		adev->uvd.inst->srbm_soft_reset = 0;1183		return false;1184	}1185}1186 1187static int uvd_v6_0_pre_soft_reset(void *handle)1188{1189	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1190 1191	if (!adev->uvd.inst->srbm_soft_reset)1192		return 0;1193 1194	uvd_v6_0_stop(adev);1195	return 0;1196}1197 1198static int uvd_v6_0_soft_reset(void *handle)1199{1200	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1201	u32 srbm_soft_reset;1202 1203	if (!adev->uvd.inst->srbm_soft_reset)1204		return 0;1205	srbm_soft_reset = adev->uvd.inst->srbm_soft_reset;1206 1207	if (srbm_soft_reset) {1208		u32 tmp;1209 1210		tmp = RREG32(mmSRBM_SOFT_RESET);1211		tmp |= srbm_soft_reset;1212		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);1213		WREG32(mmSRBM_SOFT_RESET, tmp);1214		tmp = RREG32(mmSRBM_SOFT_RESET);1215 1216		udelay(50);1217 1218		tmp &= ~srbm_soft_reset;1219		WREG32(mmSRBM_SOFT_RESET, tmp);1220		tmp = RREG32(mmSRBM_SOFT_RESET);1221 1222		/* Wait a little for things to settle down */1223		udelay(50);1224	}1225 1226	return 0;1227}1228 1229static int uvd_v6_0_post_soft_reset(void *handle)1230{1231	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1232 1233	if (!adev->uvd.inst->srbm_soft_reset)1234		return 0;1235 1236	mdelay(5);1237 1238	return uvd_v6_0_start(adev);1239}1240 1241static int uvd_v6_0_set_interrupt_state(struct amdgpu_device *adev,1242					struct amdgpu_irq_src *source,1243					unsigned type,1244					enum amdgpu_interrupt_state state)1245{1246	// TODO1247	return 0;1248}1249 1250static int uvd_v6_0_process_interrupt(struct amdgpu_device *adev,1251				      struct amdgpu_irq_src *source,1252				      struct amdgpu_iv_entry *entry)1253{1254	bool int_handled = true;1255	DRM_DEBUG("IH: UVD TRAP\n");1256 1257	switch (entry->src_id) {1258	case 124:1259		amdgpu_fence_process(&adev->uvd.inst->ring);1260		break;1261	case 119:1262		if (likely(uvd_v6_0_enc_support(adev)))1263			amdgpu_fence_process(&adev->uvd.inst->ring_enc[0]);1264		else1265			int_handled = false;1266		break;1267	case 120:1268		if (likely(uvd_v6_0_enc_support(adev)))1269			amdgpu_fence_process(&adev->uvd.inst->ring_enc[1]);1270		else1271			int_handled = false;1272		break;1273	}1274 1275	if (!int_handled)1276		DRM_ERROR("Unhandled interrupt: %d %d\n",1277			  entry->src_id, entry->src_data[0]);1278 1279	return 0;1280}1281 1282static void uvd_v6_0_enable_clock_gating(struct amdgpu_device *adev, bool enable)1283{1284	uint32_t data1, data3;1285 1286	data1 = RREG32(mmUVD_SUVD_CGC_GATE);1287	data3 = RREG32(mmUVD_CGC_GATE);1288 1289	data1 |= UVD_SUVD_CGC_GATE__SRE_MASK |1290		     UVD_SUVD_CGC_GATE__SIT_MASK |1291		     UVD_SUVD_CGC_GATE__SMP_MASK |1292		     UVD_SUVD_CGC_GATE__SCM_MASK |1293		     UVD_SUVD_CGC_GATE__SDB_MASK |1294		     UVD_SUVD_CGC_GATE__SRE_H264_MASK |1295		     UVD_SUVD_CGC_GATE__SRE_HEVC_MASK |1296		     UVD_SUVD_CGC_GATE__SIT_H264_MASK |1297		     UVD_SUVD_CGC_GATE__SIT_HEVC_MASK |1298		     UVD_SUVD_CGC_GATE__SCM_H264_MASK |1299		     UVD_SUVD_CGC_GATE__SCM_HEVC_MASK |1300		     UVD_SUVD_CGC_GATE__SDB_H264_MASK |1301		     UVD_SUVD_CGC_GATE__SDB_HEVC_MASK;1302 1303	if (enable) {1304		data3 |= (UVD_CGC_GATE__SYS_MASK       |1305			UVD_CGC_GATE__UDEC_MASK      |1306			UVD_CGC_GATE__MPEG2_MASK     |1307			UVD_CGC_GATE__RBC_MASK       |1308			UVD_CGC_GATE__LMI_MC_MASK    |1309			UVD_CGC_GATE__LMI_UMC_MASK   |1310			UVD_CGC_GATE__IDCT_MASK      |1311			UVD_CGC_GATE__MPRD_MASK      |1312			UVD_CGC_GATE__MPC_MASK       |1313			UVD_CGC_GATE__LBSI_MASK      |1314			UVD_CGC_GATE__LRBBM_MASK     |1315			UVD_CGC_GATE__UDEC_RE_MASK   |1316			UVD_CGC_GATE__UDEC_CM_MASK   |1317			UVD_CGC_GATE__UDEC_IT_MASK   |1318			UVD_CGC_GATE__UDEC_DB_MASK   |1319			UVD_CGC_GATE__UDEC_MP_MASK   |1320			UVD_CGC_GATE__WCB_MASK       |1321			UVD_CGC_GATE__JPEG_MASK      |1322			UVD_CGC_GATE__SCPU_MASK      |1323			UVD_CGC_GATE__JPEG2_MASK);1324		/* only in pg enabled, we can gate clock to vcpu*/1325		if (adev->pg_flags & AMD_PG_SUPPORT_UVD)1326			data3 |= UVD_CGC_GATE__VCPU_MASK;1327 1328		data3 &= ~UVD_CGC_GATE__REGS_MASK;1329	} else {1330		data3 = 0;1331	}1332 1333	WREG32(mmUVD_SUVD_CGC_GATE, data1);1334	WREG32(mmUVD_CGC_GATE, data3);1335}1336 1337static void uvd_v6_0_set_sw_clock_gating(struct amdgpu_device *adev)1338{1339	uint32_t data, data2;1340 1341	data = RREG32(mmUVD_CGC_CTRL);1342	data2 = RREG32(mmUVD_SUVD_CGC_CTRL);1343 1344 1345	data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK |1346		  UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK);1347 1348 1349	data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK |1350		(1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER)) |1351		(4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY));1352 1353	data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |1354			UVD_CGC_CTRL__UDEC_CM_MODE_MASK |1355			UVD_CGC_CTRL__UDEC_IT_MODE_MASK |1356			UVD_CGC_CTRL__UDEC_DB_MODE_MASK |1357			UVD_CGC_CTRL__UDEC_MP_MODE_MASK |1358			UVD_CGC_CTRL__SYS_MODE_MASK |1359			UVD_CGC_CTRL__UDEC_MODE_MASK |1360			UVD_CGC_CTRL__MPEG2_MODE_MASK |1361			UVD_CGC_CTRL__REGS_MODE_MASK |1362			UVD_CGC_CTRL__RBC_MODE_MASK |1363			UVD_CGC_CTRL__LMI_MC_MODE_MASK |1364			UVD_CGC_CTRL__LMI_UMC_MODE_MASK |1365			UVD_CGC_CTRL__IDCT_MODE_MASK |1366			UVD_CGC_CTRL__MPRD_MODE_MASK |1367			UVD_CGC_CTRL__MPC_MODE_MASK |1368			UVD_CGC_CTRL__LBSI_MODE_MASK |1369			UVD_CGC_CTRL__LRBBM_MODE_MASK |1370			UVD_CGC_CTRL__WCB_MODE_MASK |1371			UVD_CGC_CTRL__VCPU_MODE_MASK |1372			UVD_CGC_CTRL__JPEG_MODE_MASK |1373			UVD_CGC_CTRL__SCPU_MODE_MASK |1374			UVD_CGC_CTRL__JPEG2_MODE_MASK);1375	data2 &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK |1376			UVD_SUVD_CGC_CTRL__SIT_MODE_MASK |1377			UVD_SUVD_CGC_CTRL__SMP_MODE_MASK |1378			UVD_SUVD_CGC_CTRL__SCM_MODE_MASK |1379			UVD_SUVD_CGC_CTRL__SDB_MODE_MASK);1380 1381	WREG32(mmUVD_CGC_CTRL, data);1382	WREG32(mmUVD_SUVD_CGC_CTRL, data2);1383}1384 1385#if 01386static void uvd_v6_0_set_hw_clock_gating(struct amdgpu_device *adev)1387{1388	uint32_t data, data1, cgc_flags, suvd_flags;1389 1390	data = RREG32(mmUVD_CGC_GATE);1391	data1 = RREG32(mmUVD_SUVD_CGC_GATE);1392 1393	cgc_flags = UVD_CGC_GATE__SYS_MASK |1394		UVD_CGC_GATE__UDEC_MASK |1395		UVD_CGC_GATE__MPEG2_MASK |1396		UVD_CGC_GATE__RBC_MASK |1397		UVD_CGC_GATE__LMI_MC_MASK |1398		UVD_CGC_GATE__IDCT_MASK |1399		UVD_CGC_GATE__MPRD_MASK |1400		UVD_CGC_GATE__MPC_MASK |1401		UVD_CGC_GATE__LBSI_MASK |1402		UVD_CGC_GATE__LRBBM_MASK |1403		UVD_CGC_GATE__UDEC_RE_MASK |1404		UVD_CGC_GATE__UDEC_CM_MASK |1405		UVD_CGC_GATE__UDEC_IT_MASK |1406		UVD_CGC_GATE__UDEC_DB_MASK |1407		UVD_CGC_GATE__UDEC_MP_MASK |1408		UVD_CGC_GATE__WCB_MASK |1409		UVD_CGC_GATE__VCPU_MASK |1410		UVD_CGC_GATE__SCPU_MASK |1411		UVD_CGC_GATE__JPEG_MASK |1412		UVD_CGC_GATE__JPEG2_MASK;1413 1414	suvd_flags = UVD_SUVD_CGC_GATE__SRE_MASK |1415				UVD_SUVD_CGC_GATE__SIT_MASK |1416				UVD_SUVD_CGC_GATE__SMP_MASK |1417				UVD_SUVD_CGC_GATE__SCM_MASK |1418				UVD_SUVD_CGC_GATE__SDB_MASK;1419 1420	data |= cgc_flags;1421	data1 |= suvd_flags;1422 1423	WREG32(mmUVD_CGC_GATE, data);1424	WREG32(mmUVD_SUVD_CGC_GATE, data1);1425}1426#endif1427 1428static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev,1429				 bool enable)1430{1431	u32 orig, data;1432 1433	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG)) {1434		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);1435		data |= 0xfff;1436		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);1437 1438		orig = data = RREG32(mmUVD_CGC_CTRL);1439		data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;1440		if (orig != data)1441			WREG32(mmUVD_CGC_CTRL, data);1442	} else {1443		data = RREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL);1444		data &= ~0xfff;1445		WREG32_UVD_CTX(ixUVD_CGC_MEM_CTRL, data);1446 1447		orig = data = RREG32(mmUVD_CGC_CTRL);1448		data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK;1449		if (orig != data)1450			WREG32(mmUVD_CGC_CTRL, data);1451	}1452}1453 1454static int uvd_v6_0_set_clockgating_state(void *handle,1455					  enum amd_clockgating_state state)1456{1457	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1458	bool enable = (state == AMD_CG_STATE_GATE);1459 1460	if (enable) {1461		/* wait for STATUS to clear */1462		if (uvd_v6_0_wait_for_idle(handle))1463			return -EBUSY;1464		uvd_v6_0_enable_clock_gating(adev, true);1465		/* enable HW gates because UVD is idle */1466/*		uvd_v6_0_set_hw_clock_gating(adev); */1467	} else {1468		/* disable HW gating and enable Sw gating */1469		uvd_v6_0_enable_clock_gating(adev, false);1470	}1471	uvd_v6_0_set_sw_clock_gating(adev);1472	return 0;1473}1474 1475static int uvd_v6_0_set_powergating_state(void *handle,1476					  enum amd_powergating_state state)1477{1478	/* This doesn't actually powergate the UVD block.1479	 * That's done in the dpm code via the SMC.  This1480	 * just re-inits the block as necessary.  The actual1481	 * gating still happens in the dpm code.  We should1482	 * revisit this when there is a cleaner line between1483	 * the smc and the hw blocks1484	 */1485	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1486	int ret = 0;1487 1488	WREG32(mmUVD_POWER_STATUS, UVD_POWER_STATUS__UVD_PG_EN_MASK);1489 1490	if (state == AMD_PG_STATE_GATE) {1491		uvd_v6_0_stop(adev);1492	} else {1493		ret = uvd_v6_0_start(adev);1494		if (ret)1495			goto out;1496	}1497 1498out:1499	return ret;1500}1501 1502static void uvd_v6_0_get_clockgating_state(void *handle, u64 *flags)1503{1504	struct amdgpu_device *adev = (struct amdgpu_device *)handle;1505	int data;1506 1507	mutex_lock(&adev->pm.mutex);1508 1509	if (adev->flags & AMD_IS_APU)1510		data = RREG32_SMC(ixCURRENT_PG_STATUS_APU);1511	else1512		data = RREG32_SMC(ixCURRENT_PG_STATUS);1513 1514	if (data & CURRENT_PG_STATUS__UVD_PG_STATUS_MASK) {1515		DRM_INFO("Cannot get clockgating state when UVD is powergated.\n");1516		goto out;1517	}1518 1519	/* AMD_CG_SUPPORT_UVD_MGCG */1520	data = RREG32(mmUVD_CGC_CTRL);1521	if (data & UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK)1522		*flags |= AMD_CG_SUPPORT_UVD_MGCG;1523 1524out:1525	mutex_unlock(&adev->pm.mutex);1526}1527 1528static const struct amd_ip_funcs uvd_v6_0_ip_funcs = {1529	.name = "uvd_v6_0",1530	.early_init = uvd_v6_0_early_init,1531	.late_init = NULL,1532	.sw_init = uvd_v6_0_sw_init,1533	.sw_fini = uvd_v6_0_sw_fini,1534	.hw_init = uvd_v6_0_hw_init,1535	.hw_fini = uvd_v6_0_hw_fini,1536	.prepare_suspend = uvd_v6_0_prepare_suspend,1537	.suspend = uvd_v6_0_suspend,1538	.resume = uvd_v6_0_resume,1539	.is_idle = uvd_v6_0_is_idle,1540	.wait_for_idle = uvd_v6_0_wait_for_idle,1541	.check_soft_reset = uvd_v6_0_check_soft_reset,1542	.pre_soft_reset = uvd_v6_0_pre_soft_reset,1543	.soft_reset = uvd_v6_0_soft_reset,1544	.post_soft_reset = uvd_v6_0_post_soft_reset,1545	.set_clockgating_state = uvd_v6_0_set_clockgating_state,1546	.set_powergating_state = uvd_v6_0_set_powergating_state,1547	.get_clockgating_state = uvd_v6_0_get_clockgating_state,1548	.dump_ip_state = NULL,1549	.print_ip_state = NULL,1550};1551 1552static const struct amdgpu_ring_funcs uvd_v6_0_ring_phys_funcs = {1553	.type = AMDGPU_RING_TYPE_UVD,1554	.align_mask = 0xf,1555	.support_64bit_ptrs = false,1556	.no_user_fence = true,1557	.get_rptr = uvd_v6_0_ring_get_rptr,1558	.get_wptr = uvd_v6_0_ring_get_wptr,1559	.set_wptr = uvd_v6_0_ring_set_wptr,1560	.parse_cs = amdgpu_uvd_ring_parse_cs,1561	.emit_frame_size =1562		6 + /* hdp invalidate */1563		10 + /* uvd_v6_0_ring_emit_pipeline_sync */1564		14, /* uvd_v6_0_ring_emit_fence x1 no user fence */1565	.emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */1566	.emit_ib = uvd_v6_0_ring_emit_ib,1567	.emit_fence = uvd_v6_0_ring_emit_fence,1568	.emit_hdp_flush = uvd_v6_0_ring_emit_hdp_flush,1569	.test_ring = uvd_v6_0_ring_test_ring,1570	.test_ib = amdgpu_uvd_ring_test_ib,1571	.insert_nop = uvd_v6_0_ring_insert_nop,1572	.pad_ib = amdgpu_ring_generic_pad_ib,1573	.begin_use = amdgpu_uvd_ring_begin_use,1574	.end_use = amdgpu_uvd_ring_end_use,1575	.emit_wreg = uvd_v6_0_ring_emit_wreg,1576};1577 1578static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = {1579	.type = AMDGPU_RING_TYPE_UVD,1580	.align_mask = 0xf,1581	.support_64bit_ptrs = false,1582	.no_user_fence = true,1583	.get_rptr = uvd_v6_0_ring_get_rptr,1584	.get_wptr = uvd_v6_0_ring_get_wptr,1585	.set_wptr = uvd_v6_0_ring_set_wptr,1586	.emit_frame_size =1587		6 + /* hdp invalidate */1588		10 + /* uvd_v6_0_ring_emit_pipeline_sync */1589		VI_FLUSH_GPU_TLB_NUM_WREG * 6 + 8 + /* uvd_v6_0_ring_emit_vm_flush */1590		14 + 14, /* uvd_v6_0_ring_emit_fence x2 vm fence */1591	.emit_ib_size = 8, /* uvd_v6_0_ring_emit_ib */1592	.emit_ib = uvd_v6_0_ring_emit_ib,1593	.emit_fence = uvd_v6_0_ring_emit_fence,1594	.emit_vm_flush = uvd_v6_0_ring_emit_vm_flush,1595	.emit_pipeline_sync = uvd_v6_0_ring_emit_pipeline_sync,1596	.emit_hdp_flush = uvd_v6_0_ring_emit_hdp_flush,1597	.test_ring = uvd_v6_0_ring_test_ring,1598	.test_ib = amdgpu_uvd_ring_test_ib,1599	.insert_nop = uvd_v6_0_ring_insert_nop,1600	.pad_ib = amdgpu_ring_generic_pad_ib,1601	.begin_use = amdgpu_uvd_ring_begin_use,1602	.end_use = amdgpu_uvd_ring_end_use,1603	.emit_wreg = uvd_v6_0_ring_emit_wreg,1604};1605 1606static const struct amdgpu_ring_funcs uvd_v6_0_enc_ring_vm_funcs = {1607	.type = AMDGPU_RING_TYPE_UVD_ENC,1608	.align_mask = 0x3f,1609	.nop = HEVC_ENC_CMD_NO_OP,1610	.support_64bit_ptrs = false,1611	.no_user_fence = true,1612	.get_rptr = uvd_v6_0_enc_ring_get_rptr,1613	.get_wptr = uvd_v6_0_enc_ring_get_wptr,1614	.set_wptr = uvd_v6_0_enc_ring_set_wptr,1615	.emit_frame_size =1616		4 + /* uvd_v6_0_enc_ring_emit_pipeline_sync */1617		5 + /* uvd_v6_0_enc_ring_emit_vm_flush */1618		5 + 5 + /* uvd_v6_0_enc_ring_emit_fence x2 vm fence */1619		1, /* uvd_v6_0_enc_ring_insert_end */1620	.emit_ib_size = 5, /* uvd_v6_0_enc_ring_emit_ib */1621	.emit_ib = uvd_v6_0_enc_ring_emit_ib,1622	.emit_fence = uvd_v6_0_enc_ring_emit_fence,1623	.emit_vm_flush = uvd_v6_0_enc_ring_emit_vm_flush,1624	.emit_pipeline_sync = uvd_v6_0_enc_ring_emit_pipeline_sync,1625	.test_ring = uvd_v6_0_enc_ring_test_ring,1626	.test_ib = uvd_v6_0_enc_ring_test_ib,1627	.insert_nop = amdgpu_ring_insert_nop,1628	.insert_end = uvd_v6_0_enc_ring_insert_end,1629	.pad_ib = amdgpu_ring_generic_pad_ib,1630	.begin_use = amdgpu_uvd_ring_begin_use,1631	.end_use = amdgpu_uvd_ring_end_use,1632};1633 1634static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev)1635{1636	if (adev->asic_type >= CHIP_POLARIS10) {1637		adev->uvd.inst->ring.funcs = &uvd_v6_0_ring_vm_funcs;1638		DRM_INFO("UVD is enabled in VM mode\n");1639	} else {1640		adev->uvd.inst->ring.funcs = &uvd_v6_0_ring_phys_funcs;1641		DRM_INFO("UVD is enabled in physical mode\n");1642	}1643}1644 1645static void uvd_v6_0_set_enc_ring_funcs(struct amdgpu_device *adev)1646{1647	int i;1648 1649	for (i = 0; i < adev->uvd.num_enc_rings; ++i)1650		adev->uvd.inst->ring_enc[i].funcs = &uvd_v6_0_enc_ring_vm_funcs;1651 1652	DRM_INFO("UVD ENC is enabled in VM mode\n");1653}1654 1655static const struct amdgpu_irq_src_funcs uvd_v6_0_irq_funcs = {1656	.set = uvd_v6_0_set_interrupt_state,1657	.process = uvd_v6_0_process_interrupt,1658};1659 1660static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev)1661{1662	if (uvd_v6_0_enc_support(adev))1663		adev->uvd.inst->irq.num_types = adev->uvd.num_enc_rings + 1;1664	else1665		adev->uvd.inst->irq.num_types = 1;1666 1667	adev->uvd.inst->irq.funcs = &uvd_v6_0_irq_funcs;1668}1669 1670const struct amdgpu_ip_block_version uvd_v6_0_ip_block =1671{1672		.type = AMD_IP_BLOCK_TYPE_UVD,1673		.major = 6,1674		.minor = 0,1675		.rev = 0,1676		.funcs = &uvd_v6_0_ip_funcs,1677};1678 1679const struct amdgpu_ip_block_version uvd_v6_2_ip_block =1680{1681		.type = AMD_IP_BLOCK_TYPE_UVD,1682		.major = 6,1683		.minor = 2,1684		.rev = 0,1685		.funcs = &uvd_v6_0_ip_funcs,1686};1687 1688const struct amdgpu_ip_block_version uvd_v6_3_ip_block =1689{1690		.type = AMD_IP_BLOCK_TYPE_UVD,1691		.major = 6,1692		.minor = 3,1693		.rev = 0,1694		.funcs = &uvd_v6_0_ip_funcs,1695};1696