Commit 87167bb1 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/radeon: add UVD support for CIK (v3)



v2: agd5f: fix clock dividers setup for bonaire
v3: agd5f: rebase

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 9219ed65
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -1495,6 +1495,9 @@ static void cik_gpu_init(struct radeon_device *rdev)
	WREG32(DMIF_ADDR_CALC, gb_addr_config);
	WREG32(SDMA0_TILING_CONFIG + SDMA0_REGISTER_OFFSET, gb_addr_config & 0x70);
	WREG32(SDMA0_TILING_CONFIG + SDMA1_REGISTER_OFFSET, gb_addr_config & 0x70);
	WREG32(UVD_UDEC_ADDR_CONFIG, gb_addr_config);
	WREG32(UVD_UDEC_DB_ADDR_CONFIG, gb_addr_config);
	WREG32(UVD_UDEC_DBW_ADDR_CONFIG, gb_addr_config);

	cik_tiling_mode_table_init(rdev);

@@ -4906,6 +4909,16 @@ static int cik_startup(struct radeon_device *rdev)
		return r;
	}

	r = cik_uvd_resume(rdev);
	if (!r) {
		r = radeon_fence_driver_start_ring(rdev,
						   R600_RING_TYPE_UVD_INDEX);
		if (r)
			dev_err(rdev->dev, "UVD fences init error (%d).\n", r);
	}
	if (r)
		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;

	/* Enable IRQ */
	if (!rdev->irq.installed) {
		r = radeon_irq_kms_init(rdev);
@@ -4952,6 +4965,18 @@ static int cik_startup(struct radeon_device *rdev)
	if (r)
		return r;

	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
	if (ring->ring_size) {
		r = radeon_ring_init(rdev, ring, ring->ring_size,
				     R600_WB_UVD_RPTR_OFFSET,
				     UVD_RBC_RB_RPTR, UVD_RBC_RB_WPTR,
				     0, 0xfffff, RADEON_CP_PACKET2);
		if (!r)
			r = r600_uvd_init(rdev);
		if (r)
			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
	}

	r = radeon_ib_pool_init(rdev);
	if (r) {
		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -5009,6 +5034,8 @@ int cik_suspend(struct radeon_device *rdev)
	radeon_vm_manager_fini(rdev);
	cik_cp_enable(rdev, false);
	cik_sdma_enable(rdev, false);
	r600_uvd_rbc_stop(rdev);
	radeon_uvd_suspend(rdev);
	cik_irq_suspend(rdev);
	radeon_wb_disable(rdev);
	cik_pcie_gart_disable(rdev);
@@ -5092,6 +5119,13 @@ int cik_init(struct radeon_device *rdev)
	ring->ring_obj = NULL;
	r600_ring_init(rdev, ring, 256 * 1024);

	r = radeon_uvd_init(rdev);
	if (!r) {
		ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX];
		ring->ring_obj = NULL;
		r600_ring_init(rdev, ring, 4096);
	}

	rdev->ih.ring_obj = NULL;
	r600_ih_ring_init(rdev, 64 * 1024);

@@ -5146,6 +5180,7 @@ void cik_fini(struct radeon_device *rdev)
	radeon_vm_manager_fini(rdev);
	radeon_ib_pool_fini(rdev);
	radeon_irq_kms_fini(rdev);
	radeon_uvd_fini(rdev);
	cik_pcie_gart_fini(rdev);
	r600_vram_scratch_fini(rdev);
	radeon_gem_fini(rdev);
@@ -5713,3 +5748,79 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev)
	return clock;
}

static int cik_set_uvd_clock(struct radeon_device *rdev, u32 clock,
                              u32 cntl_reg, u32 status_reg)
{
	int r, i;
	struct atom_clock_dividers dividers;
	uint32_t tmp;

	r = radeon_atom_get_clock_dividers(rdev, COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK,
					   clock, false, &dividers);
	if (r)
		return r;

	tmp = RREG32_SMC(cntl_reg);
	tmp &= ~(DCLK_DIR_CNTL_EN|DCLK_DIVIDER_MASK);
	tmp |= dividers.post_divider;
	WREG32_SMC(cntl_reg, tmp);

	for (i = 0; i < 100; i++) {
		if (RREG32_SMC(status_reg) & DCLK_STATUS)
			break;
		mdelay(10);
	}
	if (i == 100)
		return -ETIMEDOUT;

	return 0;
}

int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
	int r = 0;

	r = cik_set_uvd_clock(rdev, vclk, CG_VCLK_CNTL, CG_VCLK_STATUS);
	if (r)
		return r;

	r = cik_set_uvd_clock(rdev, dclk, CG_DCLK_CNTL, CG_DCLK_STATUS);
	return r;
}

int cik_uvd_resume(struct radeon_device *rdev)
{
	uint64_t addr;
	uint32_t size;
	int r;

	r = radeon_uvd_resume(rdev);
	if (r)
		return r;

	/* programm the VCPU memory controller bits 0-27 */
	addr = rdev->uvd.gpu_addr >> 3;
	size = RADEON_GPU_PAGE_ALIGN(rdev->uvd_fw->size + 4) >> 3;
	WREG32(UVD_VCPU_CACHE_OFFSET0, addr);
	WREG32(UVD_VCPU_CACHE_SIZE0, size);

	addr += size;
	size = RADEON_UVD_STACK_SIZE >> 3;
	WREG32(UVD_VCPU_CACHE_OFFSET1, addr);
	WREG32(UVD_VCPU_CACHE_SIZE1, size);

	addr += size;
	size = RADEON_UVD_HEAP_SIZE >> 3;
	WREG32(UVD_VCPU_CACHE_OFFSET2, addr);
	WREG32(UVD_VCPU_CACHE_SIZE2, size);

	/* bits 28-31 */
	addr = (rdev->uvd.gpu_addr >> 28) & 0xF;
	WREG32(UVD_LMI_ADDR_EXT, (addr << 12) | (addr << 0));

	/* bits 32-39 */
	addr = (rdev->uvd.gpu_addr >> 32) & 0xFF;
	WREG32(UVD_LMI_EXT40_ADDR, addr | (0x9 << 16) | (0x1 << 31));

	return 0;
}
+28 −0
Original line number Diff line number Diff line
@@ -1204,4 +1204,32 @@
#       define SDMA_SRBM_WRITE_EXTRA_BYTE_ENABLE(x)       ((x) << 12)
                /* byte mask */

/* UVD */

#define UVD_UDEC_ADDR_CONFIG		0xef4c
#define UVD_UDEC_DB_ADDR_CONFIG		0xef50
#define UVD_UDEC_DBW_ADDR_CONFIG	0xef54

#define UVD_LMI_EXT40_ADDR		0xf498
#define UVD_LMI_ADDR_EXT		0xf594
#define UVD_VCPU_CACHE_OFFSET0		0xf608
#define UVD_VCPU_CACHE_SIZE0		0xf60c
#define UVD_VCPU_CACHE_OFFSET1		0xf610
#define UVD_VCPU_CACHE_SIZE1		0xf614
#define UVD_VCPU_CACHE_OFFSET2		0xf618
#define UVD_VCPU_CACHE_SIZE2		0xf61c

#define UVD_RBC_RB_RPTR			0xf690
#define UVD_RBC_RB_WPTR			0xf694

/* UVD clocks */

#define CG_DCLK_CNTL			0xC050009C
#	define DCLK_DIVIDER_MASK	0x7f
#	define DCLK_DIR_CNTL_EN		(1 << 8)
#define CG_DCLK_STATUS			0xC05000A0
#	define DCLK_STATUS		(1 << 0)
#define CG_VCLK_CNTL			0xC05000A4
#define CG_VCLK_STATUS			0xC05000A8

#endif
+2 −0
Original line number Diff line number Diff line
@@ -560,5 +560,7 @@ uint64_t cik_get_gpu_clock_counter(struct radeon_device *rdev);
u32 cik_get_xclk(struct radeon_device *rdev);
uint32_t cik_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
void cik_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk);
int cik_uvd_resume(struct radeon_device *rdev);

#endif
+8 −0
Original line number Diff line number Diff line
@@ -44,11 +44,13 @@
#define FIRMWARE_CYPRESS	"radeon/CYPRESS_uvd.bin"
#define FIRMWARE_SUMO		"radeon/SUMO_uvd.bin"
#define FIRMWARE_TAHITI		"radeon/TAHITI_uvd.bin"
#define FIRMWARE_BONAIRE	"radeon/BONAIRE_uvd.bin"

MODULE_FIRMWARE(FIRMWARE_RV710);
MODULE_FIRMWARE(FIRMWARE_CYPRESS);
MODULE_FIRMWARE(FIRMWARE_SUMO);
MODULE_FIRMWARE(FIRMWARE_TAHITI);
MODULE_FIRMWARE(FIRMWARE_BONAIRE);

static void radeon_uvd_idle_work_handler(struct work_struct *work);

@@ -100,6 +102,12 @@ int radeon_uvd_init(struct radeon_device *rdev)
		fw_name = FIRMWARE_TAHITI;
		break;

	case CHIP_BONAIRE:
	case CHIP_KABINI:
	case CHIP_KAVERI:
		fw_name = FIRMWARE_BONAIRE;
		break;

	default:
		return -EINVAL;
	}