diff options
Diffstat (limited to 'meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch')
-rw-r--r-- | meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch | 1434 |
1 files changed, 0 insertions, 1434 deletions
diff --git a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch b/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch deleted file mode 100644 index e64abef2..00000000 --- a/meta-steppeeagle/recipes-kernel/linux/linux-yocto/0027-yocto-amd-drm-radeon-initial-VCE-support-v4.patch +++ /dev/null @@ -1,1434 +0,0 @@ -From 5890ab59e66a268c7910a7a5ad939107fa1b8a1d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com> -Date: Thu, 23 May 2013 12:10:04 +0200 -Subject: [PATCH 27/44] drm/radeon: initial VCE support v4 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -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: Christian König <christian.koenig@amd.com> ---- - drivers/gpu/drm/radeon/Makefile | 6 + - drivers/gpu/drm/radeon/cik.c | 60 ++++ - drivers/gpu/drm/radeon/cikd.h | 33 ++ - drivers/gpu/drm/radeon/radeon.h | 56 +++- - drivers/gpu/drm/radeon/radeon_asic.c | 17 + - drivers/gpu/drm/radeon/radeon_asic.h | 13 + - drivers/gpu/drm/radeon/radeon_cs.c | 4 + - drivers/gpu/drm/radeon/radeon_kms.c | 1 + - drivers/gpu/drm/radeon/radeon_ring.c | 4 + - drivers/gpu/drm/radeon/radeon_test.c | 39 ++- - drivers/gpu/drm/radeon/radeon_vce.c | 588 ++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/radeon/sid.h | 47 +++ - drivers/gpu/drm/radeon/vce_v1_0.c | 187 +++++++++++ - drivers/gpu/drm/radeon/vce_v2_0.c | 70 ++++ - include/uapi/drm/radeon_drm.h | 1 + - 15 files changed, 1117 insertions(+), 9 deletions(-) - create mode 100644 drivers/gpu/drm/radeon/radeon_vce.c - create mode 100644 drivers/gpu/drm/radeon/vce_v1_0.c - create mode 100644 drivers/gpu/drm/radeon/vce_v2_0.c - -diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile -index 306364a..ed60caa 100644 ---- a/drivers/gpu/drm/radeon/Makefile -+++ b/drivers/gpu/drm/radeon/Makefile -@@ -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 -diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c -index 4a89b5c..872b146 100644 ---- a/drivers/gpu/drm/radeon/cik.c -+++ b/drivers/gpu/drm/radeon/cik.c -@@ -6753,6 +6753,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); -@@ -7071,6 +7085,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); -@@ -7146,6 +7176,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); -@@ -7213,6 +7260,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); -@@ -7321,6 +7369,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); - -@@ -7381,6 +7440,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); -diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h -index 7a0a0d2..b296d50 100644 ---- a/drivers/gpu/drm/radeon/cikd.h -+++ b/drivers/gpu/drm/radeon/cikd.h -@@ -1899,4 +1899,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 -diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h -index fb7323d..094e5f5 100644 ---- a/drivers/gpu/drm/radeon/radeon.h -+++ b/drivers/gpu/drm/radeon/radeon.h -@@ -111,19 +111,16 @@ extern int radeon_aspm; - #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 - - /* internal ring indices */ - /* r1xx+ has gfx CP ring */ --#define RADEON_RING_TYPE_GFX_INDEX 0 -+#define RADEON_RING_TYPE_GFX_INDEX 0 - - /* cayman has 2 compute CP rings */ --#define CAYMAN_RING_TYPE_CP1_INDEX 1 --#define CAYMAN_RING_TYPE_CP2_INDEX 2 -+#define CAYMAN_RING_TYPE_CP1_INDEX 1 -+#define CAYMAN_RING_TYPE_CP2_INDEX 2 - - /* R600+ has an async dma ring */ - #define R600_RING_TYPE_DMA_INDEX 3 -@@ -131,7 +128,14 @@ extern int radeon_aspm; - #define CAYMAN_RING_TYPE_DMA1_INDEX 4 - - /* R600+ */ --#define R600_RING_TYPE_UVD_INDEX 5 -+#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 - - /* hardcode those limit for now */ - #define RADEON_VA_IB_OFFSET (1 << 20) -@@ -1586,6 +1590,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; -@@ -2180,6 +2220,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; -@@ -2198,6 +2239,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 */ -diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c -index a539869..763280b 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.c -+++ b/drivers/gpu/drm/radeon/radeon_asic.c -@@ -1978,6 +1978,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, -@@ -2006,6 +2019,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, -@@ -2107,6 +2122,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, -diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h -index 998042e..a6c3eeb 100644 ---- a/drivers/gpu/drm/radeon/radeon_asic.h -+++ b/drivers/gpu/drm/radeon/radeon_asic.h -@@ -850,4 +850,17 @@ bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev, - /* uvd v4.2 */ - int uvd_v4_2_resume(struct radeon_device *rdev); - -+/* vce v1.0 */ -+uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev, -+ struct radeon_ring *ring); -+uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev, -+ struct radeon_ring *ring); -+void vce_v1_0_set_wptr(struct radeon_device *rdev, -+ struct radeon_ring *ring); -+int vce_v1_0_init(struct radeon_device *rdev); -+int vce_v1_0_start(struct radeon_device *rdev); -+ -+/* vce v2.0 */ -+int vce_v2_0_resume(struct radeon_device *rdev); -+ - #endif -diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c -index 83731ff..2f8e92b 100644 ---- a/drivers/gpu/drm/radeon/radeon_cs.c -+++ b/drivers/gpu/drm/radeon/radeon_cs.c -@@ -147,6 +147,10 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority - case RADEON_CS_RING_UVD: - p->ring = R600_RING_TYPE_UVD_INDEX; - break; -+ case RADEON_CS_RING_VCE: -+ /* TODO: only use the low priority ring for now */ -+ p->ring = TN_RING_TYPE_VCE1_INDEX; -+ break; - } - return 0; - } -diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c -index 5d67422..07da88f 100644 ---- a/drivers/gpu/drm/radeon/radeon_kms.c -+++ b/drivers/gpu/drm/radeon/radeon_kms.c -@@ -579,6 +579,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev, - if (rdev->cmask_filp == file_priv) - rdev->cmask_filp = NULL; - radeon_uvd_free_handles(rdev, file_priv); -+ radeon_vce_free_handles(rdev, file_priv); - } - - /* -diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c -index 65f1cea..91457f8 100644 ---- a/drivers/gpu/drm/radeon/radeon_ring.c -+++ b/drivers/gpu/drm/radeon/radeon_ring.c -@@ -814,6 +814,8 @@ static int cayman_cp2_index = CAYMAN_RING_TYPE_CP2_INDEX; - static int radeon_dma1_index = R600_RING_TYPE_DMA_INDEX; - static int radeon_dma2_index = CAYMAN_RING_TYPE_DMA1_INDEX; - static int r600_uvd_index = R600_RING_TYPE_UVD_INDEX; -+static int si_vce1_index = TN_RING_TYPE_VCE1_INDEX; -+static int si_vce2_index = TN_RING_TYPE_VCE2_INDEX; - - static struct drm_info_list radeon_debugfs_ring_info_list[] = { - {"radeon_ring_gfx", radeon_debugfs_ring_info, 0, &radeon_gfx_index}, -@@ -822,6 +824,8 @@ static struct drm_info_list radeon_debugfs_ring_info_list[] = { - {"radeon_ring_dma1", radeon_debugfs_ring_info, 0, &radeon_dma1_index}, - {"radeon_ring_dma2", radeon_debugfs_ring_info, 0, &radeon_dma2_index}, - {"radeon_ring_uvd", radeon_debugfs_ring_info, 0, &r600_uvd_index}, -+ {"radeon_ring_vce1", radeon_debugfs_ring_info, 0, &si_vce1_index}, -+ {"radeon_ring_vce2", radeon_debugfs_ring_info, 0, &si_vce2_index}, - }; - - static int radeon_debugfs_sa_info(struct seq_file *m, void *data) -diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c -index 12e8099..3a13e0d 100644 ---- a/drivers/gpu/drm/radeon/radeon_test.c -+++ b/drivers/gpu/drm/radeon/radeon_test.c -@@ -257,20 +257,36 @@ static int radeon_test_create_and_emit_fence(struct radeon_device *rdev, - struct radeon_ring *ring, - struct radeon_fence **fence) - { -+ uint32_t handle = ring->idx ^ 0xdeafbeef; - int r; - - if (ring->idx == R600_RING_TYPE_UVD_INDEX) { -- r = radeon_uvd_get_create_msg(rdev, ring->idx, 1, NULL); -+ r = radeon_uvd_get_create_msg(rdev, ring->idx, handle, NULL); - if (r) { - DRM_ERROR("Failed to get dummy create msg\n"); - return r; - } - -- r = radeon_uvd_get_destroy_msg(rdev, ring->idx, 1, fence); -+ r = radeon_uvd_get_destroy_msg(rdev, ring->idx, handle, fence); - if (r) { - DRM_ERROR("Failed to get dummy destroy msg\n"); - return r; - } -+ -+ } else if (ring->idx == TN_RING_TYPE_VCE1_INDEX || -+ ring->idx == TN_RING_TYPE_VCE2_INDEX) { -+ r = radeon_vce_get_create_msg(rdev, ring->idx, handle, NULL); -+ if (r) { -+ DRM_ERROR("Failed to get dummy create msg\n"); -+ return r; -+ } -+ -+ r = radeon_vce_get_destroy_msg(rdev, ring->idx, handle, fence); -+ if (r) { -+ DRM_ERROR("Failed to get dummy destroy msg\n"); -+ return r; -+ } -+ - } else { - r = radeon_ring_lock(rdev, ring, 64); - if (r) { -@@ -486,6 +502,16 @@ out_cleanup: - printk(KERN_WARNING "Error while testing ring sync (%d).\n", r); - } - -+static bool radeon_test_sync_possible(struct radeon_ring *ringA, -+ struct radeon_ring *ringB) -+{ -+ if (ringA->idx == TN_RING_TYPE_VCE2_INDEX && -+ ringB->idx == TN_RING_TYPE_VCE1_INDEX) -+ return false; -+ -+ return true; -+} -+ - void radeon_test_syncing(struct radeon_device *rdev) - { - int i, j, k; -@@ -500,6 +526,9 @@ void radeon_test_syncing(struct radeon_device *rdev) - if (!ringB->ready) - continue; - -+ if (!radeon_test_sync_possible(ringA, ringB)) -+ continue; -+ - DRM_INFO("Testing syncing between rings %d and %d...\n", i, j); - radeon_test_ring_sync(rdev, ringA, ringB); - -@@ -511,6 +540,12 @@ void radeon_test_syncing(struct radeon_device *rdev) - if (!ringC->ready) - continue; - -+ if (!radeon_test_sync_possible(ringA, ringC)) -+ continue; -+ -+ if (!radeon_test_sync_possible(ringB, ringC)) -+ continue; -+ - DRM_INFO("Testing syncing between rings %d, %d and %d...\n", i, j, k); - radeon_test_ring_sync2(rdev, ringA, ringB, ringC); - -diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c -new file mode 100644 -index 0000000..2547d8e ---- /dev/null -+++ b/drivers/gpu/drm/radeon/radeon_vce.c -@@ -0,0 +1,588 @@ -+/* -+ * Copyright 2013 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 <linux/module.h> -+#include <drm/drmP.h> -+#include <drm/drm.h> -+ -+#include "radeon.h" -+#include "radeon_asic.h" -+#include "sid.h" -+ -+/* Firmware Names */ -+#define FIRMWARE_BONAIRE "radeon/BONAIRE_vce.bin" -+ -+MODULE_FIRMWARE(FIRMWARE_BONAIRE); -+ -+/** -+ * radeon_vce_init - allocate memory, load vce firmware -+ * -+ * @rdev: radeon_device pointer -+ * -+ * First step to get VCE online, allocate memory and load the firmware -+ */ -+int radeon_vce_init(struct radeon_device *rdev) -+{ -+ unsigned long bo_size; -+ const char *fw_name; -+ int i, r; -+ -+ switch (rdev->family) { -+ case CHIP_BONAIRE: -+ case CHIP_KAVERI: -+ case CHIP_KABINI: -+ fw_name = FIRMWARE_BONAIRE; -+ break; -+ -+ default: -+ return -EINVAL; -+ } -+ -+ r = request_firmware(&rdev->vce_fw, fw_name, rdev->dev); -+ if (r) { -+ dev_err(rdev->dev, "radeon_vce: Can't load firmware \"%s\"\n", -+ fw_name); -+ return r; -+ } -+ -+ bo_size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size) + -+ RADEON_VCE_STACK_SIZE + RADEON_VCE_HEAP_SIZE; -+ r = radeon_bo_create(rdev, bo_size, PAGE_SIZE, true, -+ RADEON_GEM_DOMAIN_VRAM, NULL, &rdev->vce.vcpu_bo); -+ if (r) { -+ dev_err(rdev->dev, "(%d) failed to allocate VCE bo\n", r); -+ return r; -+ } -+ -+ r = radeon_vce_resume(rdev); -+ if (r) -+ return r; -+ -+ memset(rdev->vce.cpu_addr, 0, bo_size); -+ memcpy(rdev->vce.cpu_addr, rdev->vce_fw->data, rdev->vce_fw->size); -+ -+ r = radeon_vce_suspend(rdev); -+ if (r) -+ return r; -+ -+ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { -+ atomic_set(&rdev->vce.handles[i], 0); -+ rdev->vce.filp[i] = NULL; -+ } -+ -+ return 0; -+} -+ -+/** -+ * radeon_vce_fini - free memory -+ * -+ * @rdev: radeon_device pointer -+ * -+ * Last step on VCE teardown, free firmware memory -+ */ -+void radeon_vce_fini(struct radeon_device *rdev) -+{ -+ radeon_vce_suspend(rdev); -+ radeon_bo_unref(&rdev->vce.vcpu_bo); -+} -+ -+/** -+ * radeon_vce_suspend - unpin VCE fw memory -+ * -+ * @rdev: radeon_device pointer -+ * -+ * TODO: Test VCE suspend/resume -+ */ -+int radeon_vce_suspend(struct radeon_device *rdev) -+{ -+ int r; -+ -+ if (rdev->vce.vcpu_bo == NULL) -+ return 0; -+ -+ r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); -+ if (!r) { -+ radeon_bo_kunmap(rdev->vce.vcpu_bo); -+ radeon_bo_unpin(rdev->vce.vcpu_bo); -+ radeon_bo_unreserve(rdev->vce.vcpu_bo); -+ } -+ return r; -+} -+ -+/** -+ * radeon_vce_resume - pin VCE fw memory -+ * -+ * @rdev: radeon_device pointer -+ * -+ * TODO: Test VCE suspend/resume -+ */ -+int radeon_vce_resume(struct radeon_device *rdev) -+{ -+ int r; -+ -+ if (rdev->vce.vcpu_bo == NULL) -+ return -EINVAL; -+ -+ r = radeon_bo_reserve(rdev->vce.vcpu_bo, false); -+ if (r) { -+ radeon_bo_unref(&rdev->vce.vcpu_bo); -+ dev_err(rdev->dev, "(%d) failed to reserve VCE bo\n", r); -+ return r; -+ } -+ -+ r = radeon_bo_pin(rdev->vce.vcpu_bo, RADEON_GEM_DOMAIN_VRAM, -+ &rdev->vce.gpu_addr); -+ if (r) { -+ radeon_bo_unreserve(rdev->vce.vcpu_bo); -+ radeon_bo_unref(&rdev->vce.vcpu_bo); -+ dev_err(rdev->dev, "(%d) VCE bo pin failed\n", r); -+ return r; -+ } -+ -+ r = radeon_bo_kmap(rdev->vce.vcpu_bo, &rdev->vce.cpu_addr); -+ if (r) { -+ dev_err(rdev->dev, "(%d) VCE map failed\n", r); -+ return r; -+ } -+ -+ radeon_bo_unreserve(rdev->vce.vcpu_bo); -+ -+ return 0; -+} -+ -+/** -+ * radeon_vce_free_handles - free still open VCE handles -+ * -+ * @rdev: radeon_device pointer -+ * @filp: drm file pointer -+ * -+ * Close all VCE handles still open by this file pointer -+ */ -+void radeon_vce_free_handles(struct radeon_device *rdev, struct drm_file *filp) -+{ -+ int i, r; -+ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { -+ uint32_t handle = atomic_read(&rdev->vce.handles[i]); -+ if (!handle || rdev->vce.filp[i] != filp) -+ continue; -+ -+ r = radeon_vce_get_destroy_msg(rdev, TN_RING_TYPE_VCE1_INDEX, -+ handle, NULL); -+ if (r) -+ DRM_ERROR("Error destroying VCE handle (%d)!\n", r); -+ -+ rdev->vce.filp[i] = NULL; -+ atomic_set(&rdev->vce.handles[i], 0); -+ } -+} -+ -+/** -+ * radeon_vce_get_create_msg - generate a VCE create msg -+ * -+ * @rdev: radeon_device pointer -+ * @ring: ring we should submit the msg to -+ * @handle: VCE session handle to use -+ * @fence: optional fence to return -+ * -+ * Open up a stream for HW test -+ */ -+int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring, -+ uint32_t handle, struct radeon_fence **fence) -+{ -+ const unsigned ib_size_dw = 1024; -+ struct radeon_ib ib; -+ uint64_t dummy; -+ int i, r; -+ -+ r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4); -+ if (r) { -+ DRM_ERROR("radeon: failed to get ib (%d).\n", r); -+ return r; -+ } -+ -+ dummy = ib.gpu_addr + 1024; -+ -+ /* stitch together an VCE create msg */ -+ ib.length_dw = 0; -+ ib.ptr[ib.length_dw++] = 0x0000000c; /* len */ -+ ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */ -+ ib.ptr[ib.length_dw++] = handle; -+ -+ ib.ptr[ib.length_dw++] = 0x00000030; /* len */ -+ ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */ -+ ib.ptr[ib.length_dw++] = 0x00000000; -+ ib.ptr[ib.length_dw++] = 0x00000042; -+ ib.ptr[ib.length_dw++] = 0x0000000a; -+ ib.ptr[ib.length_dw++] = 0x00000001; -+ ib.ptr[ib.length_dw++] = 0x00000080; -+ ib.ptr[ib.length_dw++] = 0x00000060; -+ ib.ptr[ib.length_dw++] = 0x00000100; -+ ib.ptr[ib.length_dw++] = 0x00000100; -+ ib.ptr[ib.length_dw++] = 0x0000000c; -+ ib.ptr[ib.length_dw++] = 0x00000000; -+ -+ ib.ptr[ib.length_dw++] = 0x00000014; /* len */ -+ ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */ -+ ib.ptr[ib.length_dw++] = upper_32_bits(dummy); -+ ib.ptr[ib.length_dw++] = dummy; -+ ib.ptr[ib.length_dw++] = 0x00000001; -+ -+ for (i = ib.length_dw; i < ib_size_dw; ++i) -+ ib.ptr[i] = 0x0; -+ -+ r = radeon_ib_schedule(rdev, &ib, NULL); -+ if (r) { -+ DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); -+ } -+ -+ if (fence) -+ *fence = radeon_fence_ref(ib.fence); -+ -+ radeon_ib_free(rdev, &ib); -+ -+ return r; -+} -+ -+/** -+ * radeon_vce_get_destroy_msg - generate a VCE destroy msg -+ * -+ * @rdev: radeon_device pointer -+ * @ring: ring we should submit the msg to -+ * @handle: VCE session handle to use -+ * @fence: optional fence to return -+ * -+ * Close up a stream for HW test or if userspace failed to do so -+ */ -+int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring, -+ uint32_t handle, struct radeon_fence **fence) -+{ -+ const unsigned ib_size_dw = 1024; -+ struct radeon_ib ib; -+ uint64_t dummy; -+ int i, r; -+ -+ r = radeon_ib_get(rdev, ring, &ib, NULL, ib_size_dw * 4); -+ if (r) { -+ DRM_ERROR("radeon: failed to get ib (%d).\n", r); -+ return r; -+ } -+ -+ dummy = ib.gpu_addr + 1024; -+ -+ /* stitch together an VCE destroy msg */ -+ ib.length_dw = 0; -+ ib.ptr[ib.length_dw++] = 0x0000000c; /* len */ -+ ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */ -+ ib.ptr[ib.length_dw++] = handle; -+ -+ ib.ptr[ib.length_dw++] = 0x00000014; /* len */ -+ ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */ -+ ib.ptr[ib.length_dw++] = upper_32_bits(dummy); -+ ib.ptr[ib.length_dw++] = dummy; -+ ib.ptr[ib.length_dw++] = 0x00000001; -+ -+ ib.ptr[ib.length_dw++] = 0x00000008; /* len */ -+ ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */ -+ -+ for (i = ib.length_dw; i < ib_size_dw; ++i) -+ ib.ptr[i] = 0x0; -+ -+ r = radeon_ib_schedule(rdev, &ib, NULL); -+ if (r) { -+ DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); -+ } -+ -+ if (fence) -+ *fence = radeon_fence_ref(ib.fence); -+ -+ radeon_ib_free(rdev, &ib); -+ -+ return r; -+} -+ -+/** -+ * radeon_vce_cs_reloc - command submission relocation -+ * -+ * @p: parser context -+ * @lo: address of lower dword -+ * @hi: address of higher dword -+ * -+ * Patch relocation inside command stream with real buffer address -+ */ -+int radeon_vce_cs_reloc(struct radeon_cs_parser *p, int lo, int hi) -+{ -+ struct radeon_cs_chunk *relocs_chunk; -+ uint64_t offset; -+ unsigned idx; -+ -+ relocs_chunk = &p->chunks[p->chunk_relocs_idx]; -+ offset = radeon_get_ib_value(p, lo); -+ idx = radeon_get_ib_value(p, hi); -+ -+ if (idx >= relocs_chunk->length_dw) { -+ DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", -+ idx, relocs_chunk->length_dw); -+ return -EINVAL; -+ } -+ -+ offset += p->relocs_ptr[(idx / 4)]->lobj.gpu_offset; -+ -+ p->ib.ptr[lo] = offset & 0xFFFFFFFF; -+ p->ib.ptr[hi] = offset >> 32; -+ -+ return 0; -+} -+ -+/** -+ * radeon_vce_cs_parse - parse and validate the command stream -+ * -+ * @p: parser context -+ * -+ */ -+int radeon_vce_cs_parse(struct radeon_cs_parser *p) -+{ -+ uint32_t handle = 0; -+ bool destroy = false; -+ int i, r; -+ -+ while (p->idx < p->chunks[p->chunk_ib_idx].length_dw) { -+ uint32_t len = radeon_get_ib_value(p, p->idx); -+ uint32_t cmd = radeon_get_ib_value(p, p->idx + 1); -+ -+ if ((len < 8) || (len & 3)) { -+ DRM_ERROR("invalid VCE command length (%d)!\n", len); -+ return -EINVAL; -+ } -+ -+ switch (cmd) { -+ case 0x00000001: // session -+ handle = radeon_get_ib_value(p, p->idx + 2); -+ break; -+ -+ case 0x00000002: // task info -+ case 0x01000001: // create -+ case 0x04000001: // config extension -+ case 0x04000002: // pic control -+ case 0x04000005: // rate control -+ case 0x04000007: // motion estimation -+ case 0x04000008: // rdo -+ break; -+ -+ case 0x03000001: // encode -+ r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9); -+ if (r) -+ return r; -+ -+ r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11); -+ if (r) -+ return r; -+ break; -+ -+ case 0x02000001: // destroy -+ destroy = true; -+ break; -+ -+ case 0x05000001: // context buffer -+ case 0x05000004: // video bitstream buffer -+ case 0x05000005: // feedback buffer -+ r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2); -+ if (r) -+ return r; -+ break; -+ -+ default: -+ DRM_ERROR("invalid VCE command (0x%x)!\n", cmd); -+ return -EINVAL; -+ } -+ -+ p->idx += len / 4; -+ } -+ -+ if (destroy) { -+ /* IB contains a destroy msg, free the handle */ -+ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) -+ atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0); -+ -+ return 0; -+ } -+ -+ /* create or encode, validate the handle */ -+ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { -+ if (atomic_read(&p->rdev->vce.handles[i]) == handle) -+ return 0; -+ } -+ -+ /* handle not found try to alloc a new one */ -+ for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) { -+ if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) { -+ p->rdev->vce.filp[i] = p->filp; -+ return 0; -+ } -+ } -+ -+ DRM_ERROR("No more free VCE handles!\n"); -+ return -EINVAL; -+} -+ -+/** -+ * radeon_vce_semaphore_emit - emit a semaphore command -+ * -+ * @rdev: radeon_device pointer -+ * @ring: engine to use -+ * @semaphore: address of semaphore -+ * @emit_wait: true=emit wait, false=emit signal -+ * -+ */ -+bool radeon_vce_semaphore_emit(struct radeon_device *rdev, -+ struct radeon_ring *ring, -+ struct radeon_semaphore *semaphore, -+ bool emit_wait) -+{ -+ uint64_t addr = semaphore->gpu_addr; -+ -+ radeon_ring_write(ring, VCE_CMD_SEMAPHORE); -+ radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF); -+ radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF); -+ radeon_ring_write(ring, 0x01003000 | (emit_wait ? 1 : 0)); -+ if (!emit_wait) -+ radeon_ring_write(ring, VCE_CMD_END); -+ -+ return true; -+} -+ -+/** -+ * radeon_vce_ib_execute - execute indirect buffer -+ * -+ * @rdev: radeon_device pointer -+ * @ib: the IB to execute -+ * -+ */ -+void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) -+{ -+ struct radeon_ring *ring = &rdev->ring[ib->ring]; -+ radeon_ring_write(ring, VCE_CMD_IB); -+ radeon_ring_write(ring, ib->gpu_addr); -+ radeon_ring_write(ring, upper_32_bits(ib->gpu_addr)); -+ radeon_ring_write(ring, ib->length_dw); -+} -+ -+/** -+ * radeon_vce_fence_emit - add a fence command to the ring -+ * -+ * @rdev: radeon_device pointer -+ * @fence: the fence -+ * -+ */ -+void radeon_vce_fence_emit(struct radeon_device *rdev, -+ struct radeon_fence *fence) -+{ -+ struct radeon_ring *ring = &rdev->ring[fence->ring]; -+ uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr; -+ -+ radeon_ring_write(ring, VCE_CMD_FENCE); -+ radeon_ring_write(ring, addr); -+ radeon_ring_write(ring, upper_32_bits(addr)); -+ radeon_ring_write(ring, fence->seq); -+ radeon_ring_write(ring, VCE_CMD_TRAP); -+ radeon_ring_write(ring, VCE_CMD_END); -+} -+ -+/** -+ * radeon_vce_ring_test - test if VCE ring is working -+ * -+ * @rdev: radeon_device pointer -+ * @ring: the engine to test on -+ * -+ */ -+int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) -+{ -+ uint32_t rptr = vce_v1_0_get_rptr(rdev, ring); -+ unsigned i; -+ int r; -+ -+ r = radeon_ring_lock(rdev, ring, 16); -+ if (r) { -+ DRM_ERROR("radeon: vce failed to lock ring %d (%d).\n", -+ ring->idx, r); -+ return r; -+ } -+ radeon_ring_write(ring, VCE_CMD_END); -+ radeon_ring_unlock_commit(rdev, ring); -+ -+ for (i = 0; i < rdev->usec_timeout; i++) { -+ if (vce_v1_0_get_rptr(rdev, ring) != rptr) -+ break; -+ DRM_UDELAY(1); -+ } -+ -+ if (i < rdev->usec_timeout) { -+ DRM_INFO("ring test on %d succeeded in %d usecs\n", -+ ring->idx, i); -+ } else { -+ DRM_ERROR("radeon: ring %d test failed\n", -+ ring->idx); -+ r = -ETIMEDOUT; -+ } -+ -+ return r; -+} -+ -+/** -+ * radeon_vce_ib_test - test if VCE IBs are working -+ * -+ * @rdev: radeon_device pointer -+ * @ring: the engine to test on -+ * -+ */ -+int radeon_vce_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) -+{ -+ struct radeon_fence *fence = NULL; -+ int r; -+ -+ r = radeon_vce_get_create_msg(rdev, ring->idx, 1, NULL); -+ if (r) { -+ DRM_ERROR("radeon: failed to get create msg (%d).\n", r); -+ goto error; -+ } -+ -+ r = radeon_vce_get_destroy_msg(rdev, ring->idx, 1, &fence); -+ if (r) { -+ DRM_ERROR("radeon: failed to get destroy ib (%d).\n", r); -+ goto error; -+ } -+ -+ r = radeon_fence_wait(fence, false); -+ if (r) { -+ DRM_ERROR("radeon: fence wait failed (%d).\n", r); -+ } else { -+ DRM_INFO("ib test on ring %d succeeded\n", ring->idx); -+ } -+error: -+ radeon_fence_unref(&fence); -+ return r; -+} -diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h -index db3dd87..1da5a7a 100644 ---- a/drivers/gpu/drm/radeon/sid.h -+++ b/drivers/gpu/drm/radeon/sid.h -@@ -1747,4 +1747,51 @@ - #define DMA_PACKET_CONSTANT_FILL 0xd - #define DMA_PACKET_NOP 0xf - -+#define VCE_STATUS 0x20004 -+#define VCE_VCPU_CNTL 0x20014 -+#define VCE_CLK_EN (1 << 0) -+#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_SOFT_RESET 0x20120 -+#define VCE_ECPU_SOFT_RESET (1 << 0) -+#define VCE_FME_SOFT_RESET (1 << 2) -+#define VCE_RB_BASE_LO2 0x2016c -+#define VCE_RB_BASE_HI2 0x20170 -+#define VCE_RB_SIZE2 0x20174 -+#define VCE_RB_RPTR2 0x20178 -+#define VCE_RB_WPTR2 0x2017c -+#define VCE_RB_BASE_LO 0x20180 -+#define VCE_RB_BASE_HI 0x20184 -+#define VCE_RB_SIZE 0x20188 -+#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 0x205bc -+#define VCE_UENC_REG_CLOCK_GATING 0x205c0 -+#define VCE_FW_REG_STATUS 0x20e10 -+# define VCE_FW_REG_STATUS_BUSY (1 << 0) -+# define VCE_FW_REG_STATUS_PASS (1 << 3) -+# define VCE_FW_REG_STATUS_DONE (1 << 11) -+#define VCE_LMI_FW_START_KEYSEL 0x20e18 -+#define VCE_LMI_FW_PERIODIC_CTRL 0x20e20 -+#define VCE_LMI_CTRL2 0x20e74 -+#define VCE_LMI_CTRL 0x20e98 -+#define VCE_LMI_VM_CTRL 0x20ea0 -+#define VCE_LMI_SWAP_CNTL 0x20eb4 -+#define VCE_LMI_SWAP_CNTL1 0x20eb8 -+#define VCE_LMI_CACHE_CTRL 0x20ef4 -+ -+#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 -diff --git a/drivers/gpu/drm/radeon/vce_v1_0.c b/drivers/gpu/drm/radeon/vce_v1_0.c -new file mode 100644 -index 0000000..e0c3534 ---- /dev/null -+++ b/drivers/gpu/drm/radeon/vce_v1_0.c -@@ -0,0 +1,187 @@ -+/* -+ * Copyright 2013 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 "radeon.h" -+#include "radeon_asic.h" -+#include "sid.h" -+ -+/** -+ * vce_v1_0_get_rptr - get read pointer -+ * -+ * @rdev: radeon_device pointer -+ * @ring: radeon_ring pointer -+ * -+ * Returns the current hardware read pointer -+ */ -+uint32_t vce_v1_0_get_rptr(struct radeon_device *rdev, -+ struct radeon_ring *ring) -+{ -+ if (ring->idx == TN_RING_TYPE_VCE1_INDEX) -+ return RREG32(VCE_RB_RPTR); -+ else -+ return RREG32(VCE_RB_RPTR2); -+} -+ -+/** -+ * vce_v1_0_get_wptr - get write pointer -+ * -+ * @rdev: radeon_device pointer -+ * @ring: radeon_ring pointer -+ * -+ * Returns the current hardware write pointer -+ */ -+uint32_t vce_v1_0_get_wptr(struct radeon_device *rdev, -+ struct radeon_ring *ring) -+{ -+ if (ring->idx == TN_RING_TYPE_VCE1_INDEX) -+ return RREG32(VCE_RB_WPTR); -+ else -+ return RREG32(VCE_RB_WPTR2); -+} -+ -+/** -+ * vce_v1_0_set_wptr - set write pointer -+ * -+ * @rdev: radeon_device pointer -+ * @ring: radeon_ring pointer -+ * -+ * Commits the write pointer to the hardware -+ */ -+void vce_v1_0_set_wptr(struct radeon_device *rdev, -+ struct radeon_ring *ring) -+{ -+ if (ring->idx == TN_RING_TYPE_VCE1_INDEX) -+ WREG32(VCE_RB_WPTR, ring->wptr); -+ else -+ WREG32(VCE_RB_WPTR2, ring->wptr); -+} -+ -+/** -+ * vce_v1_0_start - start VCE block -+ * -+ * @rdev: radeon_device pointer -+ * -+ * Setup and start the VCE block -+ */ -+int vce_v1_0_start(struct radeon_device *rdev) -+{ -+ struct radeon_ring *ring; -+ int i, j, r; -+ -+ /* set BUSY flag */ -+ WREG32_P(VCE_STATUS, 1, ~1); -+ -+ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; -+ WREG32(VCE_RB_RPTR, ring->rptr); -+ WREG32(VCE_RB_WPTR, ring->wptr); -+ WREG32(VCE_RB_BASE_LO, ring->gpu_addr); -+ WREG32(VCE_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); -+ WREG32(VCE_RB_SIZE, ring->ring_size / 4); -+ -+ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; -+ WREG32(VCE_RB_RPTR2, ring->rptr); -+ WREG32(VCE_RB_WPTR2, ring->wptr); -+ WREG32(VCE_RB_BASE_LO2, ring->gpu_addr); -+ WREG32(VCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); -+ WREG32(VCE_RB_SIZE2, ring->ring_size / 4); -+ -+ WREG32_P(VCE_VCPU_CNTL, VCE_CLK_EN, ~VCE_CLK_EN); -+ -+ WREG32_P(VCE_SOFT_RESET, -+ VCE_ECPU_SOFT_RESET | -+ VCE_FME_SOFT_RESET, ~( -+ VCE_ECPU_SOFT_RESET | -+ VCE_FME_SOFT_RESET)); -+ -+ mdelay(100); -+ -+ WREG32_P(VCE_SOFT_RESET, 0, ~( -+ VCE_ECPU_SOFT_RESET | -+ VCE_FME_SOFT_RESET)); -+ -+ for (i = 0; i < 10; ++i) { -+ uint32_t status; -+ for (j = 0; j < 100; ++j) { -+ status = RREG32(VCE_STATUS); -+ if (status & 2) -+ break; -+ mdelay(10); -+ } -+ r = 0; -+ if (status & 2) -+ break; -+ -+ DRM_ERROR("VCE not responding, trying to reset the ECPU!!!\n"); -+ WREG32_P(VCE_SOFT_RESET, VCE_ECPU_SOFT_RESET, ~VCE_ECPU_SOFT_RESET); -+ mdelay(10); -+ WREG32_P(VCE_SOFT_RESET, 0, ~VCE_ECPU_SOFT_RESET); -+ mdelay(10); -+ r = -1; -+ } -+ -+ /* clear BUSY flag */ -+ WREG32_P(VCE_STATUS, 0, ~1); -+ -+ if (r) { -+ DRM_ERROR("VCE not responding, giving up!!!\n"); -+ return r; -+ } -+ -+ return 0; -+} -+ -+int vce_v1_0_init(struct radeon_device *rdev) -+{ -+ struct radeon_ring *ring; -+ int r; -+ -+ r = vce_v1_0_start(rdev); -+ if (r) -+ return r; -+ -+ ring = &rdev->ring[TN_RING_TYPE_VCE1_INDEX]; -+ ring->ready = true; -+ r = radeon_ring_test(rdev, TN_RING_TYPE_VCE1_INDEX, ring); -+ if (r) { -+ ring->ready = false; -+ return r; -+ } -+ -+ ring = &rdev->ring[TN_RING_TYPE_VCE2_INDEX]; -+ ring->ready = true; -+ r = radeon_ring_test(rdev, TN_RING_TYPE_VCE2_INDEX, ring); -+ if (r) { -+ ring->ready = false; -+ return r; -+ } -+ -+ DRM_INFO("VCE initialized successfully.\n"); -+ -+ return 0; -+} -diff --git a/drivers/gpu/drm/radeon/vce_v2_0.c b/drivers/gpu/drm/radeon/vce_v2_0.c -new file mode 100644 -index 0000000..4911d1b ---- /dev/null -+++ b/drivers/gpu/drm/radeon/vce_v2_0.c -@@ -0,0 +1,70 @@ -+/* -+ * Copyright 2013 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 "radeon.h" -+#include "radeon_asic.h" -+#include "cikd.h" -+ -+int vce_v2_0_resume(struct radeon_device *rdev) -+{ -+ uint64_t addr = rdev->vce.gpu_addr; -+ uint32_t size; -+ -+ WREG32_P(VCE_CLOCK_GATING_A, 0, ~(1 << 16)); -+ WREG32_P(VCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000); -+ WREG32_P(VCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F); -+ WREG32(VCE_CLOCK_GATING_B, 0xf7); -+ -+ WREG32(VCE_LMI_CTRL, 0x00398000); -+ WREG32_P(VCE_LMI_CACHE_CTRL, 0x0, ~0x1); -+ WREG32(VCE_LMI_SWAP_CNTL, 0); -+ WREG32(VCE_LMI_SWAP_CNTL1, 0); -+ WREG32(VCE_LMI_VM_CTRL, 0); -+ -+ size = RADEON_GPU_PAGE_ALIGN(rdev->vce_fw->size); -+ WREG32(VCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff); -+ WREG32(VCE_VCPU_CACHE_SIZE0, size); -+ -+ addr += size; -+ size = RADEON_VCE_STACK_SIZE; -+ WREG32(VCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff); -+ WREG32(VCE_VCPU_CACHE_SIZE1, size); -+ -+ addr += size; -+ size = RADEON_VCE_HEAP_SIZE; -+ WREG32(VCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff); -+ WREG32(VCE_VCPU_CACHE_SIZE2, size); -+ -+ WREG32_P(VCE_LMI_CTRL2, 0x0, ~0x100); -+ -+ WREG32_P(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, -+ ~VCE_SYS_INT_TRAP_INTERRUPT_EN); -+ -+ return 0; -+} -diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h -index fe421e8..b93c92a 100644 ---- a/include/uapi/drm/radeon_drm.h -+++ b/include/uapi/drm/radeon_drm.h -@@ -919,6 +919,7 @@ struct drm_radeon_gem_va { - #define RADEON_CS_RING_COMPUTE 1 - #define RADEON_CS_RING_DMA 2 - #define RADEON_CS_RING_UVD 3 -+#define RADEON_CS_RING_VCE 4 - /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ - /* 0 = normal, + = higher priority, - = lower priority */ - --- -1.7.9.5 - |