vce_v3_0.c 21.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
/*
 * Copyright 2014 Advanced Micro Devices, Inc.
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * Authors: Christian König <christian.koenig@amd.com>
 */

#include <linux/firmware.h>
#include <drm/drmP.h>
#include "amdgpu.h"
#include "amdgpu_vce.h"
#include "vid.h"
#include "vce/vce_3_0_d.h"
#include "vce/vce_3_0_sh_mask.h"
35 36
#include "oss/oss_3_0_d.h"
#include "oss/oss_3_0_sh_mask.h"
37
#include "gca/gfx_8_0_d.h"
38 39
#include "smu/smu_7_1_2_d.h"
#include "smu/smu_7_1_2_sh_mask.h"
40 41 42
#include "gca/gfx_8_0_d.h"
#include "gca/gfx_8_0_sh_mask.h"

43 44 45

#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT	0x04
#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK	0x10
46 47 48
#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0	0x8616
#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1	0x8617
#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2	0x8618
J
jimqu 已提交
49
#define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK	0x02
50

51 52 53 54
#define VCE_V3_0_FW_SIZE	(384 * 1024)
#define VCE_V3_0_STACK_SIZE	(64 * 1024)
#define VCE_V3_0_DATA_SIZE	((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024))

55
static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
56 57
static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
J
jimqu 已提交
58
static int vce_v3_0_wait_for_idle(void *handle);
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110

/**
 * vce_v3_0_ring_get_rptr - get read pointer
 *
 * @ring: amdgpu_ring pointer
 *
 * Returns the current hardware read pointer
 */
static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring)
{
	struct amdgpu_device *adev = ring->adev;

	if (ring == &adev->vce.ring[0])
		return RREG32(mmVCE_RB_RPTR);
	else
		return RREG32(mmVCE_RB_RPTR2);
}

/**
 * vce_v3_0_ring_get_wptr - get write pointer
 *
 * @ring: amdgpu_ring pointer
 *
 * Returns the current hardware write pointer
 */
static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring)
{
	struct amdgpu_device *adev = ring->adev;

	if (ring == &adev->vce.ring[0])
		return RREG32(mmVCE_RB_WPTR);
	else
		return RREG32(mmVCE_RB_WPTR2);
}

/**
 * vce_v3_0_ring_set_wptr - set write pointer
 *
 * @ring: amdgpu_ring pointer
 *
 * Commits the write pointer to the hardware
 */
static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring)
{
	struct amdgpu_device *adev = ring->adev;

	if (ring == &adev->vce.ring[0])
		WREG32(mmVCE_RB_WPTR, ring->wptr);
	else
		WREG32(mmVCE_RB_WPTR2, ring->wptr);
}

111 112
static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override)
{
113
	WREG32_FIELD(VCE_RB_ARB_CTRL, VCE_CGTT_OVERRIDE, override ? 1 : 0);
114 115 116 117 118
}

static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev,
					     bool gated)
{
119
	u32 data;
120

121 122 123
	/* Set Override to disable Clock Gating */
	vce_v3_0_override_vce_clock_gating(adev, true);

124 125 126 127 128 129
	/* This function enables MGCG which is controlled by firmware.
	   With the clocks in the gated state the core is still
	   accessible but the firmware will throttle the clocks on the
	   fly as necessary.
	*/
	if (gated) {
130
		data = RREG32(mmVCE_CLOCK_GATING_B);
131 132
		data |= 0x1ff;
		data &= ~0xef0000;
133
		WREG32(mmVCE_CLOCK_GATING_B, data);
134

135
		data = RREG32(mmVCE_UENC_CLOCK_GATING);
136 137
		data |= 0x3ff000;
		data &= ~0xffc00000;
138
		WREG32(mmVCE_UENC_CLOCK_GATING, data);
139

140
		data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
141
		data |= 0x2;
142
		data &= ~0x00010000;
143
		WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
144

145
		data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
146
		data |= 0x37f;
147
		WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
148

149
		data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
150
		data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
151 152 153
			VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
			VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK  |
			0x8;
154
		WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
155
	} else {
156
		data = RREG32(mmVCE_CLOCK_GATING_B);
157 158
		data &= ~0x80010;
		data |= 0xe70008;
159
		WREG32(mmVCE_CLOCK_GATING_B, data);
160

161
		data = RREG32(mmVCE_UENC_CLOCK_GATING);
162
		data |= 0xffc00000;
163
		WREG32(mmVCE_UENC_CLOCK_GATING, data);
164

165
		data = RREG32(mmVCE_UENC_CLOCK_GATING_2);
166
		data |= 0x10000;
167
		WREG32(mmVCE_UENC_CLOCK_GATING_2, data);
168

169
		data = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
170
		data &= ~0xffc00000;
171
		WREG32(mmVCE_UENC_REG_CLOCK_GATING, data);
172

173
		data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL);
174
		data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK |
175 176 177
			  VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK |
			  VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK  |
			  0x8);
178
		WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data);
179 180 181 182
	}
	vce_v3_0_override_vce_clock_gating(adev, false);
}

J
jimqu 已提交
183 184 185 186 187 188
static int vce_v3_0_firmware_loaded(struct amdgpu_device *adev)
{
	int i, j;

	for (i = 0; i < 10; ++i) {
		for (j = 0; j < 100; ++j) {
J
jimqu 已提交
189 190
			uint32_t status = RREG32(mmVCE_STATUS);

J
jimqu 已提交
191 192 193 194 195 196
			if (status & VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK)
				return 0;
			mdelay(10);
		}

		DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n");
197
		WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 1);
J
jimqu 已提交
198
		mdelay(10);
199
		WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 0);
J
jimqu 已提交
200 201 202 203 204 205
		mdelay(10);
	}

	return -ETIMEDOUT;
}

206 207 208 209 210 211 212 213 214 215
/**
 * vce_v3_0_start - start VCE block
 *
 * @adev: amdgpu_device pointer
 *
 * Setup and start the VCE block
 */
static int vce_v3_0_start(struct amdgpu_device *adev)
{
	struct amdgpu_ring *ring;
J
jimqu 已提交
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
	int idx, r;

	ring = &adev->vce.ring[0];
	WREG32(mmVCE_RB_RPTR, ring->wptr);
	WREG32(mmVCE_RB_WPTR, ring->wptr);
	WREG32(mmVCE_RB_BASE_LO, ring->gpu_addr);
	WREG32(mmVCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr));
	WREG32(mmVCE_RB_SIZE, ring->ring_size / 4);

	ring = &adev->vce.ring[1];
	WREG32(mmVCE_RB_RPTR2, ring->wptr);
	WREG32(mmVCE_RB_WPTR2, ring->wptr);
	WREG32(mmVCE_RB_BASE_LO2, ring->gpu_addr);
	WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr));
	WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4);
231 232 233

	mutex_lock(&adev->grbm_idx_mutex);
	for (idx = 0; idx < 2; ++idx) {
234 235 236
		if (adev->vce.harvest_config & (1 << idx))
			continue;

237
		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
238
		vce_v3_0_mc_resume(adev, idx);
239
		WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
J
jimqu 已提交
240

241 242 243
		if (adev->asic_type >= CHIP_STONEY)
			WREG32_P(mmVCE_VCPU_CNTL, 1, ~0x200001);
		else
244
			WREG32_FIELD(VCE_VCPU_CNTL, CLK_EN, 1);
245

246
		WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 0);
J
jimqu 已提交
247 248 249
		mdelay(100);

		r = vce_v3_0_firmware_loaded(adev);
250 251

		/* clear BUSY flag */
252
		WREG32_FIELD(VCE_STATUS, JOB_BUSY, 0);
253

254 255 256 257 258 259
		if (r) {
			DRM_ERROR("VCE not responding, giving up!!!\n");
			mutex_unlock(&adev->grbm_idx_mutex);
			return r;
		}
	}
260

261
	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
262
	mutex_unlock(&adev->grbm_idx_mutex);
263

J
jimqu 已提交
264 265
	return 0;
}
266

J
jimqu 已提交
267 268 269 270 271 272 273 274 275
static int vce_v3_0_stop(struct amdgpu_device *adev)
{
	int idx;

	mutex_lock(&adev->grbm_idx_mutex);
	for (idx = 0; idx < 2; ++idx) {
		if (adev->vce.harvest_config & (1 << idx))
			continue;

276
		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
J
jimqu 已提交
277 278 279 280

		if (adev->asic_type >= CHIP_STONEY)
			WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x200001);
		else
281 282
			WREG32_FIELD(VCE_VCPU_CNTL, CLK_EN, 0);

J
jimqu 已提交
283
		/* hold on ECPU */
284
		WREG32_FIELD(VCE_SOFT_RESET, ECPU_SOFT_RESET, 1);
J
jimqu 已提交
285 286

		/* clear BUSY flag */
287
		WREG32_FIELD(VCE_STATUS, JOB_BUSY, 0);
J
jimqu 已提交
288 289 290 291 292 293

		/* Set Clock-Gating off */
		if (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)
			vce_v3_0_set_vce_sw_clock_gating(adev, false);
	}

294
	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
J
jimqu 已提交
295
	mutex_unlock(&adev->grbm_idx_mutex);
296 297 298 299

	return 0;
}

300 301 302 303 304 305 306 307
#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS     0xC0014074
#define VCE_HARVEST_FUSE_MACRO__SHIFT       27
#define VCE_HARVEST_FUSE_MACRO__MASK        0x18000000

static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
{
	u32 tmp;

308
	/* Fiji, Stoney, Polaris10, Polaris11 are single pipe */
309
	if ((adev->asic_type == CHIP_FIJI) ||
310
	    (adev->asic_type == CHIP_STONEY) ||
311 312
	    (adev->asic_type == CHIP_POLARIS10) ||
	    (adev->asic_type == CHIP_POLARIS11))
313
		return AMDGPU_VCE_HARVEST_VCE1;
314 315

	/* Tonga and CZ are dual or single pipe */
316
	if (adev->flags & AMD_IS_APU)
317 318 319 320 321 322 323 324 325 326
		tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
		       VCE_HARVEST_FUSE_MACRO__MASK) >>
			VCE_HARVEST_FUSE_MACRO__SHIFT;
	else
		tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
		       CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
			CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;

	switch (tmp) {
	case 1:
327
		return AMDGPU_VCE_HARVEST_VCE0;
328
	case 2:
329
		return AMDGPU_VCE_HARVEST_VCE1;
330
	case 3:
331
		return AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
332
	default:
333
		return 0;
334 335 336
	}
}

337
static int vce_v3_0_early_init(void *handle)
338
{
339 340
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

341 342 343 344 345 346 347
	adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);

	if ((adev->vce.harvest_config &
	     (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
	    (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
		return -ENOENT;

348 349 350 351 352 353
	vce_v3_0_set_ring_funcs(adev);
	vce_v3_0_set_irq_funcs(adev);

	return 0;
}

354
static int vce_v3_0_sw_init(void *handle)
355
{
356
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
357 358 359 360 361 362 363 364
	struct amdgpu_ring *ring;
	int r;

	/* VCE */
	r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq);
	if (r)
		return r;

365 366
	r = amdgpu_vce_sw_init(adev, VCE_V3_0_FW_SIZE +
		(VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE) * 2);
367 368 369 370 371 372 373 374 375
	if (r)
		return r;

	r = amdgpu_vce_resume(adev);
	if (r)
		return r;

	ring = &adev->vce.ring[0];
	sprintf(ring->name, "vce0");
376
	r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
377 378 379 380 381 382
			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
	if (r)
		return r;

	ring = &adev->vce.ring[1];
	sprintf(ring->name, "vce1");
383
	r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf,
384 385 386 387 388 389 390
			     &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE);
	if (r)
		return r;

	return r;
}

391
static int vce_v3_0_sw_fini(void *handle)
392 393
{
	int r;
394
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
395 396 397 398 399 400 401 402 403 404 405 406

	r = amdgpu_vce_suspend(adev);
	if (r)
		return r;

	r = amdgpu_vce_sw_fini(adev);
	if (r)
		return r;

	return r;
}

407
static int vce_v3_0_hw_init(void *handle)
408
{
409
	int r, i;
410
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
411 412 413 414 415

	r = vce_v3_0_start(adev);
	if (r)
		return r;

416 417
	adev->vce.ring[0].ready = false;
	adev->vce.ring[1].ready = false;
418

419 420 421 422 423 424
	for (i = 0; i < 2; i++) {
		r = amdgpu_ring_test_ring(&adev->vce.ring[i]);
		if (r)
			return r;
		else
			adev->vce.ring[i].ready = true;
425 426 427 428 429 430 431
	}

	DRM_INFO("VCE initialized successfully.\n");

	return 0;
}

432
static int vce_v3_0_hw_fini(void *handle)
433
{
J
jimqu 已提交
434 435 436 437 438 439 440 441
	int r;
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	r = vce_v3_0_wait_for_idle(handle);
	if (r)
		return r;

	return vce_v3_0_stop(adev);
442 443
}

444
static int vce_v3_0_suspend(void *handle)
445 446
{
	int r;
447
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
448 449 450 451 452 453 454 455 456 457 458 459

	r = vce_v3_0_hw_fini(adev);
	if (r)
		return r;

	r = amdgpu_vce_suspend(adev);
	if (r)
		return r;

	return r;
}

460
static int vce_v3_0_resume(void *handle)
461 462
{
	int r;
463
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
464 465 466 467 468 469 470 471 472 473 474 475

	r = amdgpu_vce_resume(adev);
	if (r)
		return r;

	r = vce_v3_0_hw_init(adev);
	if (r)
		return r;

	return r;
}

476
static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx)
477 478 479 480 481 482
{
	uint32_t offset, size;

	WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
	WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
	WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
483
	WREG32(mmVCE_CLOCK_GATING_B, 0x1FF);
484 485 486 487 488 489

	WREG32(mmVCE_LMI_CTRL, 0x00398000);
	WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
	WREG32(mmVCE_LMI_SWAP_CNTL, 0);
	WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
	WREG32(mmVCE_LMI_VM_CTRL, 0);
490 491 492 493 494 495
	if (adev->asic_type >= CHIP_STONEY) {
		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR0, (adev->vce.gpu_addr >> 8));
		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR1, (adev->vce.gpu_addr >> 8));
		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR2, (adev->vce.gpu_addr >> 8));
	} else
		WREG32(mmVCE_LMI_VCPU_CACHE_40BIT_BAR, (adev->vce.gpu_addr >> 8));
496
	offset = AMDGPU_VCE_FIRMWARE_OFFSET;
497
	size = VCE_V3_0_FW_SIZE;
498 499 500
	WREG32(mmVCE_VCPU_CACHE_OFFSET0, offset & 0x7fffffff);
	WREG32(mmVCE_VCPU_CACHE_SIZE0, size);

501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
	if (idx == 0) {
		offset += size;
		size = VCE_V3_0_STACK_SIZE;
		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0x7fffffff);
		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
		offset += size;
		size = VCE_V3_0_DATA_SIZE;
		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0x7fffffff);
		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
	} else {
		offset += size + VCE_V3_0_STACK_SIZE + VCE_V3_0_DATA_SIZE;
		size = VCE_V3_0_STACK_SIZE;
		WREG32(mmVCE_VCPU_CACHE_OFFSET1, offset & 0xfffffff);
		WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
		offset += size;
		size = VCE_V3_0_DATA_SIZE;
		WREG32(mmVCE_VCPU_CACHE_OFFSET2, offset & 0xfffffff);
		WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
	}
520 521

	WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
522
	WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1);
523 524
}

525
static bool vce_v3_0_is_idle(void *handle)
526
{
527
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
528 529
	u32 mask = 0;

530 531
	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE0) ? 0 : SRBM_STATUS2__VCE0_BUSY_MASK;
	mask |= (adev->vce.harvest_config & AMDGPU_VCE_HARVEST_VCE1) ? 0 : SRBM_STATUS2__VCE1_BUSY_MASK;
532 533

	return !(RREG32(mmSRBM_STATUS2) & mask);
534 535
}

536
static int vce_v3_0_wait_for_idle(void *handle)
537 538
{
	unsigned i;
539
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
540

541 542
	for (i = 0; i < adev->usec_timeout; i++)
		if (vce_v3_0_is_idle(handle))
543
			return 0;
544

545 546 547
	return -ETIMEDOUT;
}

548 549 550 551 552
#define  VCE_STATUS_VCPU_REPORT_AUTO_BUSY_MASK  0x00000008L   /* AUTO_BUSY */
#define  VCE_STATUS_VCPU_REPORT_RB0_BUSY_MASK   0x00000010L   /* RB0_BUSY */
#define  VCE_STATUS_VCPU_REPORT_RB1_BUSY_MASK   0x00000020L   /* RB1_BUSY */
#define  AMDGPU_VCE_STATUS_BUSY_MASK (VCE_STATUS_VCPU_REPORT_AUTO_BUSY_MASK | \
				      VCE_STATUS_VCPU_REPORT_RB0_BUSY_MASK)
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571

static int vce_v3_0_check_soft_reset(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	u32 srbm_soft_reset = 0;

	/* According to VCE team , we should use VCE_STATUS instead
	 * SRBM_STATUS.VCE_BUSY bit for busy status checking.
	 * GRBM_GFX_INDEX.INSTANCE_INDEX is used to specify which VCE
	 * instance's registers are accessed
	 * (0 for 1st instance, 10 for 2nd instance).
	 *
	 *VCE_STATUS
	 *|UENC|ACPI|AUTO ACTIVE|RB1 |RB0 |RB2 |          |FW_LOADED|JOB |
	 *|----+----+-----------+----+----+----+----------+---------+----|
	 *|bit8|bit7|    bit6   |bit5|bit4|bit3|   bit2   |  bit1   |bit0|
	 *
	 * VCE team suggest use bit 3--bit 6 for busy status check
	 */
572
	mutex_lock(&adev->grbm_idx_mutex);
573
	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
574 575 576 577
	if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
	}
578
	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10);
579 580 581 582
	if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
		srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
	}
583
	WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
584 585 586 587 588 589 590 591

	if (srbm_soft_reset) {
		adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = true;
		adev->vce.srbm_soft_reset = srbm_soft_reset;
	} else {
		adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = false;
		adev->vce.srbm_soft_reset = 0;
	}
592
	mutex_unlock(&adev->grbm_idx_mutex);
593 594 595
	return 0;
}

596
static int vce_v3_0_soft_reset(void *handle)
597
{
598
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
599 600 601 602 603 604 605 606
	u32 srbm_soft_reset;

	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
		return 0;
	srbm_soft_reset = adev->vce.srbm_soft_reset;

	if (srbm_soft_reset) {
		u32 tmp;
607

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
		tmp = RREG32(mmSRBM_SOFT_RESET);
		tmp |= srbm_soft_reset;
		dev_info(adev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp);
		WREG32(mmSRBM_SOFT_RESET, tmp);
		tmp = RREG32(mmSRBM_SOFT_RESET);

		udelay(50);

		tmp &= ~srbm_soft_reset;
		WREG32(mmSRBM_SOFT_RESET, tmp);
		tmp = RREG32(mmSRBM_SOFT_RESET);

		/* Wait a little for things to settle down */
		udelay(50);
	}

	return 0;
}

static int vce_v3_0_pre_soft_reset(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
		return 0;

	mdelay(5);

	return vce_v3_0_suspend(adev);
}


static int vce_v3_0_post_soft_reset(void *handle)
{
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

	if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang)
		return 0;
646

647 648
	mdelay(5);

649
	return vce_v3_0_resume(adev);
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
}

static int vce_v3_0_set_interrupt_state(struct amdgpu_device *adev,
					struct amdgpu_irq_src *source,
					unsigned type,
					enum amdgpu_interrupt_state state)
{
	uint32_t val = 0;

	if (state == AMDGPU_IRQ_STATE_ENABLE)
		val |= VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK;

	WREG32_P(mmVCE_SYS_INT_EN, val, ~VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
	return 0;
}

static int vce_v3_0_process_interrupt(struct amdgpu_device *adev,
				      struct amdgpu_irq_src *source,
				      struct amdgpu_iv_entry *entry)
{
	DRM_DEBUG("IH: VCE\n");
671

672
	WREG32_FIELD(VCE_SYS_INT_STATUS, VCE_SYS_INT_TRAP_INTERRUPT_INT, 1);
673

674 675 676
	switch (entry->src_data) {
	case 0:
	case 1:
677
		amdgpu_fence_process(&adev->vce.ring[entry->src_data]);
678 679 680 681 682 683 684 685 686 687
		break;
	default:
		DRM_ERROR("Unhandled interrupt: %d %d\n",
			  entry->src_id, entry->src_data);
		break;
	}

	return 0;
}

R
Rex Zhu 已提交
688 689 690 691 692 693 694 695 696 697 698 699
static void vce_v3_set_bypass_mode(struct amdgpu_device *adev, bool enable)
{
	u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL);

	if (enable)
		tmp |= GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK;
	else
		tmp &= ~GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK;

	WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp);
}

700 701
static int vce_v3_0_set_clockgating_state(void *handle,
					  enum amd_clockgating_state state)
702
{
703 704 705 706
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
	bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
	int i;

R
Rex Zhu 已提交
707 708 709
	if (adev->asic_type == CHIP_POLARIS10)
		vce_v3_set_bypass_mode(adev, enable);

710
	if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG))
711 712 713 714 715 716 717 718
		return 0;

	mutex_lock(&adev->grbm_idx_mutex);
	for (i = 0; i < 2; i++) {
		/* Program VCE Instance 0 or 1 if not harvested */
		if (adev->vce.harvest_config & (1 << i))
			continue;

719
		WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, i);
720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737

		if (enable) {
			/* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
			uint32_t data = RREG32(mmVCE_CLOCK_GATING_A);
			data &= ~(0xf | 0xff0);
			data |= ((0x0 << 0) | (0x04 << 4));
			WREG32(mmVCE_CLOCK_GATING_A, data);

			/* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */
			data = RREG32(mmVCE_UENC_CLOCK_GATING);
			data &= ~(0xf | 0xff0);
			data |= ((0x0 << 0) | (0x04 << 4));
			WREG32(mmVCE_UENC_CLOCK_GATING, data);
		}

		vce_v3_0_set_vce_sw_clock_gating(adev, enable);
	}

738
	WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
739 740
	mutex_unlock(&adev->grbm_idx_mutex);

741 742 743
	return 0;
}

744 745
static int vce_v3_0_set_powergating_state(void *handle,
					  enum amd_powergating_state state)
746 747 748 749 750 751 752 753
{
	/* This doesn't actually powergate the VCE block.
	 * That's done in the dpm code via the SMC.  This
	 * just re-inits the block as necessary.  The actual
	 * gating still happens in the dpm code.  We should
	 * revisit this when there is a cleaner line between
	 * the smc and the hw blocks
	 */
754 755
	struct amdgpu_device *adev = (struct amdgpu_device *)handle;

756
	if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
757 758
		return 0;

759
	if (state == AMD_PG_STATE_GATE)
760 761 762 763 764 765
		/* XXX do we need a vce_v3_0_stop()? */
		return 0;
	else
		return vce_v3_0_start(adev);
}

766
const struct amd_ip_funcs vce_v3_0_ip_funcs = {
767
	.name = "vce_v3_0",
768 769 770 771 772 773 774 775 776 777
	.early_init = vce_v3_0_early_init,
	.late_init = NULL,
	.sw_init = vce_v3_0_sw_init,
	.sw_fini = vce_v3_0_sw_fini,
	.hw_init = vce_v3_0_hw_init,
	.hw_fini = vce_v3_0_hw_fini,
	.suspend = vce_v3_0_suspend,
	.resume = vce_v3_0_resume,
	.is_idle = vce_v3_0_is_idle,
	.wait_for_idle = vce_v3_0_wait_for_idle,
778 779
	.check_soft_reset = vce_v3_0_check_soft_reset,
	.pre_soft_reset = vce_v3_0_pre_soft_reset,
780
	.soft_reset = vce_v3_0_soft_reset,
781
	.post_soft_reset = vce_v3_0_post_soft_reset,
782 783 784 785 786 787 788 789 790 791 792 793 794
	.set_clockgating_state = vce_v3_0_set_clockgating_state,
	.set_powergating_state = vce_v3_0_set_powergating_state,
};

static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = {
	.get_rptr = vce_v3_0_ring_get_rptr,
	.get_wptr = vce_v3_0_ring_get_wptr,
	.set_wptr = vce_v3_0_ring_set_wptr,
	.parse_cs = amdgpu_vce_ring_parse_cs,
	.emit_ib = amdgpu_vce_ring_emit_ib,
	.emit_fence = amdgpu_vce_ring_emit_fence,
	.test_ring = amdgpu_vce_ring_test_ring,
	.test_ib = amdgpu_vce_ring_test_ib,
795
	.insert_nop = amdgpu_ring_insert_nop,
796
	.pad_ib = amdgpu_ring_generic_pad_ib,
797 798
	.begin_use = amdgpu_vce_ring_begin_use,
	.end_use = amdgpu_vce_ring_end_use,
799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816
};

static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev)
{
	adev->vce.ring[0].funcs = &vce_v3_0_ring_funcs;
	adev->vce.ring[1].funcs = &vce_v3_0_ring_funcs;
}

static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = {
	.set = vce_v3_0_set_interrupt_state,
	.process = vce_v3_0_process_interrupt,
};

static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev)
{
	adev->vce.irq.num_types = 1;
	adev->vce.irq.funcs = &vce_v3_0_irq_funcs;
};