Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d93f7937 authored by Christian König's avatar Christian König
Browse files

drm/radeon: initial VCE support v4



Only VCE 2.0 support so far.

v2: squashing multiple patches into this one
v3: add IRQ support for CIK, major cleanups,
    basic code documentation
v4: remove HAINAN from chipset list

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
parent 1c61eae4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -99,6 +99,12 @@ radeon-y += \
	uvd_v3_1.o \
	uvd_v4_2.o

# add VCE block
radeon-y += \
	radeon_vce.o \
	vce_v1_0.o \
	vce_v2_0.o \

radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
radeon-$(CONFIG_ACPI) += radeon_acpi.o
+60 −0
Original line number Diff line number Diff line
@@ -7490,6 +7490,20 @@ restart_ih:
			/* reset addr and status */
			WREG32_P(VM_CONTEXT1_CNTL2, 1, ~1);
			break;
		case 167: /* VCE */
			DRM_DEBUG("IH: VCE int: 0x%08x\n", src_data);
			switch (src_data) {
			case 0:
				radeon_fence_process(rdev, TN_RING_TYPE_VCE1_INDEX);
				break;
			case 1:
				radeon_fence_process(rdev, TN_RING_TYPE_VCE2_INDEX);
				break;
			default:
				DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
				break;
			}
			break;
		case 176: /* GFX RB CP_INT */
		case 177: /* GFX IB CP_INT */
			radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX);
@@ -7789,6 +7803,22 @@ static int cik_startup(struct radeon_device *rdev)
	if (r)
		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0;

	r = radeon_vce_resume(rdev);
	if (!r) {
		r = vce_v2_0_resume(rdev);
		if (!r)
			r = radeon_fence_driver_start_ring(rdev,
							   TN_RING_TYPE_VCE1_INDEX);
		if (!r)
			r = radeon_fence_driver_start_ring(rdev,
							   TN_RING_TYPE_VCE2_INDEX);
	}
	if (r) {
		dev_err(rdev->dev, "VCE init error (%d).\n", r);
		rdev->ring[TN_RING_TYPE_VCE1_INDEX].ring_size = 0;
		rdev->ring[TN_RING_TYPE_VCE2_INDEX].ring_size = 0;
	}

	/* Enable IRQ */
	if (!rdev->irq.installed) {
		r = radeon_irq_kms_init(rdev);
@@ -7864,6 +7894,23 @@ static int cik_startup(struct radeon_device *rdev)
			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r);
	}

	r = -ENOENT;

	ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX];
	if (ring->ring_size)
		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
				     VCE_CMD_NO_OP);

	ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
	if (ring->ring_size)
		r = radeon_ring_init(rdev, ring, ring->ring_size, 0,
				     VCE_CMD_NO_OP);

	if (!r)
		r = vce_v1_0_init(rdev);
	else if (r != -ENOENT)
		DRM_ERROR("radeon: failed initializing VCE (%d).\n", r);

	r = radeon_ib_pool_init(rdev);
	if (r) {
		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
@@ -7934,6 +7981,7 @@ int cik_suspend(struct radeon_device *rdev)
	cik_sdma_enable(rdev, false);
	uvd_v1_0_fini(rdev);
	radeon_uvd_suspend(rdev);
	radeon_vce_suspend(rdev);
	cik_fini_pg(rdev);
	cik_fini_cg(rdev);
	cik_irq_suspend(rdev);
@@ -8066,6 +8114,17 @@ int cik_init(struct radeon_device *rdev)
		r600_ring_init(rdev, ring, 4096);
	}

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

		ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX];
		ring->ring_obj = NULL;
		r600_ring_init(rdev, ring, 4096);
	}

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

@@ -8127,6 +8186,7 @@ void cik_fini(struct radeon_device *rdev)
	radeon_irq_kms_fini(rdev);
	uvd_v1_0_fini(rdev);
	radeon_uvd_fini(rdev);
	radeon_vce_fini(rdev);
	cik_pcie_gart_fini(rdev);
	r600_vram_scratch_fini(rdev);
	radeon_gem_fini(rdev);
+33 −0
Original line number Diff line number Diff line
@@ -2010,4 +2010,37 @@
/* UVD CTX indirect */
#define	UVD_CGC_MEM_CTRL				0xC0

/* VCE */

#define VCE_VCPU_CACHE_OFFSET0		0x20024
#define VCE_VCPU_CACHE_SIZE0		0x20028
#define VCE_VCPU_CACHE_OFFSET1		0x2002c
#define VCE_VCPU_CACHE_SIZE1		0x20030
#define VCE_VCPU_CACHE_OFFSET2		0x20034
#define VCE_VCPU_CACHE_SIZE2		0x20038
#define VCE_RB_RPTR2			0x20178
#define VCE_RB_WPTR2			0x2017c
#define VCE_RB_RPTR			0x2018c
#define VCE_RB_WPTR			0x20190
#define VCE_CLOCK_GATING_A		0x202f8
#define VCE_CLOCK_GATING_B		0x202fc
#define VCE_UENC_CLOCK_GATING		0x207bc
#define VCE_UENC_REG_CLOCK_GATING	0x207c0
#define VCE_SYS_INT_EN			0x21300
#	define VCE_SYS_INT_TRAP_INTERRUPT_EN	(1 << 3)
#define VCE_LMI_CTRL2			0x21474
#define VCE_LMI_CTRL			0x21498
#define VCE_LMI_VM_CTRL			0x214a0
#define VCE_LMI_SWAP_CNTL		0x214b4
#define VCE_LMI_SWAP_CNTL1		0x214b8
#define VCE_LMI_CACHE_CTRL		0x214f4

#define VCE_CMD_NO_OP		0x00000000
#define VCE_CMD_END		0x00000001
#define VCE_CMD_IB		0x00000002
#define VCE_CMD_FENCE		0x00000003
#define VCE_CMD_TRAP		0x00000004
#define VCE_CMD_IB_AUTO		0x00000005
#define VCE_CMD_SEMAPHORE	0x00000006

#endif
+49 −7
Original line number Diff line number Diff line
@@ -113,9 +113,6 @@ extern int radeon_hard_reset;
#define RADEONFB_CONN_LIMIT			4
#define RADEON_BIOS_NUM_SCRATCH			8

/* max number of rings */
#define RADEON_NUM_RINGS			6

/* fence seq are set to this number when signaled */
#define RADEON_FENCE_SIGNALED_SEQ		0LL

@@ -135,6 +132,13 @@ extern int radeon_hard_reset;
/* R600+ */
#define R600_RING_TYPE_UVD_INDEX		5

/* TN+ */
#define TN_RING_TYPE_VCE1_INDEX			6
#define TN_RING_TYPE_VCE2_INDEX			7

/* max number of rings */
#define RADEON_NUM_RINGS			8

/* number of hw syncs before falling back on blocking */
#define RADEON_NUM_SYNCS			4

@@ -1591,6 +1595,42 @@ int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev,
int radeon_uvd_send_upll_ctlreq(struct radeon_device *rdev,
                                unsigned cg_upll_func_cntl);

/*
 * VCE
 */
#define RADEON_MAX_VCE_HANDLES	16
#define RADEON_VCE_STACK_SIZE	(1024*1024)
#define RADEON_VCE_HEAP_SIZE	(4*1024*1024)

struct radeon_vce {
	struct radeon_bo	*vcpu_bo;
	void			*cpu_addr;
	uint64_t		gpu_addr;
	atomic_t		handles[RADEON_MAX_VCE_HANDLES];
	struct drm_file		*filp[RADEON_MAX_VCE_HANDLES];
};

int radeon_vce_init(struct radeon_device *rdev);
void radeon_vce_fini(struct radeon_device *rdev);
int radeon_vce_suspend(struct radeon_device *rdev);
int radeon_vce_resume(struct radeon_device *rdev);
int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
			      uint32_t handle, struct radeon_fence **fence);
int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
			       uint32_t handle, struct radeon_fence **fence);
void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp);
int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi);
int radeon_vce_cs_parse(struct radeon_cs_parser *p);
bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
			       struct radeon_ring *ring,
			       struct radeon_semaphore *semaphore,
			       bool emit_wait);
void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
void radeon_vce_fence_emit(struct radeon_device *rdev,
			   struct radeon_fence *fence);
int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring);
int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring);

struct r600_audio_pin {
	int			channels;
	int			rate;
@@ -2186,6 +2226,7 @@ struct radeon_device {
	struct radeon_gem		gem;
	struct radeon_pm		pm;
	struct radeon_uvd		uvd;
	struct radeon_vce		vce;
	uint32_t			bios_scratch[RADEON_BIOS_NUM_SCRATCH];
	struct radeon_wb		wb;
	struct radeon_dummy_page	dummy_page;
@@ -2205,6 +2246,7 @@ struct radeon_device {
	const struct firmware *sdma_fw;	/* CIK SDMA firmware */
	const struct firmware *smc_fw;	/* SMC firmware */
	const struct firmware *uvd_fw;	/* UVD firmware */
	const struct firmware *vce_fw;	/* VCE firmware */
	struct r600_vram_scratch vram_scratch;
	int msi_enabled; /* msi enabled */
	struct r600_ih ih; /* r6/700 interrupt ring */
+17 −0
Original line number Diff line number Diff line
@@ -1987,6 +1987,19 @@ static struct radeon_asic_ring ci_dma_ring = {
	.set_wptr = &cik_sdma_set_wptr,
};

static struct radeon_asic_ring ci_vce_ring = {
	.ib_execute = &radeon_vce_ib_execute,
	.emit_fence = &radeon_vce_fence_emit,
	.emit_semaphore = &radeon_vce_semaphore_emit,
	.cs_parse = &radeon_vce_cs_parse,
	.ring_test = &radeon_vce_ring_test,
	.ib_test = &radeon_vce_ib_test,
	.is_lockup = &radeon_ring_test_lockup,
	.get_rptr = &vce_v1_0_get_rptr,
	.get_wptr = &vce_v1_0_get_wptr,
	.set_wptr = &vce_v1_0_set_wptr,
};

static struct radeon_asic ci_asic = {
	.init = &cik_init,
	.fini = &cik_fini,
@@ -2015,6 +2028,8 @@ static struct radeon_asic ci_asic = {
		[R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring,
		[CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring,
		[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
		[TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring,
		[TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring,
	},
	.irq = {
		.set = &cik_irq_set,
@@ -2117,6 +2132,8 @@ static struct radeon_asic kv_asic = {
		[R600_RING_TYPE_DMA_INDEX] = &ci_dma_ring,
		[CAYMAN_RING_TYPE_DMA1_INDEX] = &ci_dma_ring,
		[R600_RING_TYPE_UVD_INDEX] = &cayman_uvd_ring,
		[TN_RING_TYPE_VCE1_INDEX] = &ci_vce_ring,
		[TN_RING_TYPE_VCE2_INDEX] = &ci_vce_ring,
	},
	.irq = {
		.set = &cik_irq_set,
Loading