diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/vce_v3_0.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 148 |
1 files changed, 122 insertions, 26 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 615b8b16ad04..a6b4e27bee89 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -70,8 +70,10 @@ static uint32_t vce_v3_0_ring_get_rptr(struct amdgpu_ring *ring) if (ring == &adev->vce.ring[0]) return RREG32(mmVCE_RB_RPTR); - else + else if (ring == &adev->vce.ring[1]) return RREG32(mmVCE_RB_RPTR2); + else + return RREG32(mmVCE_RB_RPTR3); } /** @@ -87,8 +89,10 @@ static uint32_t vce_v3_0_ring_get_wptr(struct amdgpu_ring *ring) if (ring == &adev->vce.ring[0]) return RREG32(mmVCE_RB_WPTR); - else + else if (ring == &adev->vce.ring[1]) return RREG32(mmVCE_RB_WPTR2); + else + return RREG32(mmVCE_RB_WPTR3); } /** @@ -104,8 +108,10 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) if (ring == &adev->vce.ring[0]) WREG32(mmVCE_RB_WPTR, ring->wptr); - else + else if (ring == &adev->vce.ring[1]) WREG32(mmVCE_RB_WPTR2, ring->wptr); + else + WREG32(mmVCE_RB_WPTR3, ring->wptr); } static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) @@ -229,6 +235,13 @@ static int vce_v3_0_start(struct amdgpu_device *adev) WREG32(mmVCE_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); WREG32(mmVCE_RB_SIZE2, ring->ring_size / 4); + ring = &adev->vce.ring[2]; + WREG32(mmVCE_RB_RPTR3, ring->wptr); + WREG32(mmVCE_RB_WPTR3, ring->wptr); + WREG32(mmVCE_RB_BASE_LO3, ring->gpu_addr); + WREG32(mmVCE_RB_BASE_HI3, upper_32_bits(ring->gpu_addr)); + WREG32(mmVCE_RB_SIZE3, ring->ring_size / 4); + mutex_lock(&adev->grbm_idx_mutex); for (idx = 0; idx < 2; ++idx) { if (adev->vce.harvest_config & (1 << idx)) @@ -345,6 +358,8 @@ static int vce_v3_0_early_init(void *handle) (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) return -ENOENT; + adev->vce.num_rings = 3; + vce_v3_0_set_ring_funcs(adev); vce_v3_0_set_irq_funcs(adev); @@ -355,7 +370,7 @@ static int vce_v3_0_sw_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ring *ring; - int r; + int r, i; /* VCE */ r = amdgpu_irq_add_id(adev, 167, &adev->vce.irq); @@ -371,19 +386,14 @@ static int vce_v3_0_sw_init(void *handle) if (r) return r; - ring = &adev->vce.ring[0]; - sprintf(ring->name, "vce0"); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); - if (r) - return r; - - ring = &adev->vce.ring[1]; - sprintf(ring->name, "vce1"); - r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, - &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); - if (r) - return r; + for (i = 0; i < adev->vce.num_rings; i++) { + ring = &adev->vce.ring[i]; + sprintf(ring->name, "vce%d", i); + r = amdgpu_ring_init(adev, ring, 512, VCE_CMD_NO_OP, 0xf, + &adev->vce.irq, 0, AMDGPU_RING_TYPE_VCE); + if (r) + return r; + } return r; } @@ -413,10 +423,10 @@ static int vce_v3_0_hw_init(void *handle) if (r) return r; - adev->vce.ring[0].ready = false; - adev->vce.ring[1].ready = false; + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].ready = false; - for (i = 0; i < 2; i++) { + for (i = 0; i < adev->vce.num_rings; i++) { r = amdgpu_ring_test_ring(&adev->vce.ring[i]); if (r) return r; @@ -674,6 +684,7 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, switch (entry->src_data) { case 0: case 1: + case 2: amdgpu_fence_process(&adev->vce.ring[entry->src_data]); break; default: @@ -685,7 +696,7 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, return 0; } -static void vce_v3_set_bypass_mode(struct amdgpu_device *adev, bool enable) +static void vce_v3_0_set_bypass_mode(struct amdgpu_device *adev, bool enable) { u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL); @@ -704,8 +715,9 @@ static int vce_v3_0_set_clockgating_state(void *handle, bool enable = (state == AMD_CG_STATE_GATE) ? true : false; int i; - if (adev->asic_type == CHIP_POLARIS10) - vce_v3_set_bypass_mode(adev, enable); + if ((adev->asic_type == CHIP_POLARIS10) || + (adev->asic_type == CHIP_TONGA)) + vce_v3_0_set_bypass_mode(adev, enable); if (!(adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) return 0; @@ -763,6 +775,60 @@ static int vce_v3_0_set_powergating_state(void *handle, return vce_v3_0_start(adev); } +static void vce_v3_0_ring_emit_ib(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, unsigned int vm_id, bool ctx_switch) +{ + amdgpu_ring_write(ring, VCE_CMD_IB_VM); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, ib->length_dw); +} + +static void vce_v3_0_emit_vm_flush(struct amdgpu_ring *ring, + unsigned int vm_id, uint64_t pd_addr) +{ + amdgpu_ring_write(ring, VCE_CMD_UPDATE_PTB); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, pd_addr >> 12); + + amdgpu_ring_write(ring, VCE_CMD_FLUSH_TLB); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, VCE_CMD_END); +} + +static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring) +{ + uint32_t seq = ring->fence_drv.sync_seq; + uint64_t addr = ring->fence_drv.gpu_addr; + + amdgpu_ring_write(ring, VCE_CMD_WAIT_GE); + amdgpu_ring_write(ring, lower_32_bits(addr)); + amdgpu_ring_write(ring, upper_32_bits(addr)); + amdgpu_ring_write(ring, seq); +} + +static unsigned vce_v3_0_ring_get_emit_ib_size(struct amdgpu_ring *ring) +{ + return + 5; /* vce_v3_0_ring_emit_ib */ +} + +static unsigned vce_v3_0_ring_get_dma_frame_size(struct amdgpu_ring *ring) +{ + return + 4 + /* vce_v3_0_emit_pipeline_sync */ + 6; /* amdgpu_vce_ring_emit_fence x1 no user fence */ +} + +static unsigned vce_v3_0_ring_get_dma_frame_size_vm(struct amdgpu_ring *ring) +{ + return + 6 + /* vce_v3_0_emit_vm_flush */ + 4 + /* vce_v3_0_emit_pipeline_sync */ + 6 + 6; /* amdgpu_vce_ring_emit_fence x2 vm fence */ +} + const struct amd_ip_funcs vce_v3_0_ip_funcs = { .name = "vce_v3_0", .early_init = vce_v3_0_early_init, @@ -783,7 +849,7 @@ const struct amd_ip_funcs vce_v3_0_ip_funcs = { .set_powergating_state = vce_v3_0_set_powergating_state, }; -static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { +static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_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, @@ -796,12 +862,42 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_funcs = { .pad_ib = amdgpu_ring_generic_pad_ib, .begin_use = amdgpu_vce_ring_begin_use, .end_use = amdgpu_vce_ring_end_use, + .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size, + .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size, +}; + +static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_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 = NULL, + .emit_ib = vce_v3_0_ring_emit_ib, + .emit_vm_flush = vce_v3_0_emit_vm_flush, + .emit_pipeline_sync = vce_v3_0_emit_pipeline_sync, + .emit_fence = amdgpu_vce_ring_emit_fence, + .test_ring = amdgpu_vce_ring_test_ring, + .test_ib = amdgpu_vce_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, + .pad_ib = amdgpu_ring_generic_pad_ib, + .begin_use = amdgpu_vce_ring_begin_use, + .end_use = amdgpu_vce_ring_end_use, + .get_emit_ib_size = vce_v3_0_ring_get_emit_ib_size, + .get_dma_frame_size = vce_v3_0_ring_get_dma_frame_size_vm, }; 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; + int i; + + if (adev->asic_type >= CHIP_STONEY) { + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].funcs = &vce_v3_0_ring_vm_funcs; + DRM_INFO("VCE enabled in VM mode\n"); + } else { + for (i = 0; i < adev->vce.num_rings; i++) + adev->vce.ring[i].funcs = &vce_v3_0_ring_phys_funcs; + DRM_INFO("VCE enabled in physical mode\n"); + } } static const struct amdgpu_irq_src_funcs vce_v3_0_irq_funcs = { |