diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/cik_sdma.c')
-rw-r--r-- | drivers/gpu/drm/radeon/cik_sdma.c | 120 |
1 files changed, 106 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index d08b83c6267b..1ecb3f1070e3 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c | |||
@@ -52,6 +52,75 @@ u32 cik_gpu_check_soft_reset(struct radeon_device *rdev); | |||
52 | */ | 52 | */ |
53 | 53 | ||
54 | /** | 54 | /** |
55 | * cik_sdma_get_rptr - get the current read pointer | ||
56 | * | ||
57 | * @rdev: radeon_device pointer | ||
58 | * @ring: radeon ring pointer | ||
59 | * | ||
60 | * Get the current rptr from the hardware (CIK+). | ||
61 | */ | ||
62 | uint32_t cik_sdma_get_rptr(struct radeon_device *rdev, | ||
63 | struct radeon_ring *ring) | ||
64 | { | ||
65 | u32 rptr, reg; | ||
66 | |||
67 | if (rdev->wb.enabled) { | ||
68 | rptr = rdev->wb.wb[ring->rptr_offs/4]; | ||
69 | } else { | ||
70 | if (ring->idx == R600_RING_TYPE_DMA_INDEX) | ||
71 | reg = SDMA0_GFX_RB_RPTR + SDMA0_REGISTER_OFFSET; | ||
72 | else | ||
73 | reg = SDMA0_GFX_RB_RPTR + SDMA1_REGISTER_OFFSET; | ||
74 | |||
75 | rptr = RREG32(reg); | ||
76 | } | ||
77 | |||
78 | return (rptr & 0x3fffc) >> 2; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * cik_sdma_get_wptr - get the current write pointer | ||
83 | * | ||
84 | * @rdev: radeon_device pointer | ||
85 | * @ring: radeon ring pointer | ||
86 | * | ||
87 | * Get the current wptr from the hardware (CIK+). | ||
88 | */ | ||
89 | uint32_t cik_sdma_get_wptr(struct radeon_device *rdev, | ||
90 | struct radeon_ring *ring) | ||
91 | { | ||
92 | u32 reg; | ||
93 | |||
94 | if (ring->idx == R600_RING_TYPE_DMA_INDEX) | ||
95 | reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET; | ||
96 | else | ||
97 | reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET; | ||
98 | |||
99 | return (RREG32(reg) & 0x3fffc) >> 2; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * cik_sdma_set_wptr - commit the write pointer | ||
104 | * | ||
105 | * @rdev: radeon_device pointer | ||
106 | * @ring: radeon ring pointer | ||
107 | * | ||
108 | * Write the wptr back to the hardware (CIK+). | ||
109 | */ | ||
110 | void cik_sdma_set_wptr(struct radeon_device *rdev, | ||
111 | struct radeon_ring *ring) | ||
112 | { | ||
113 | u32 reg; | ||
114 | |||
115 | if (ring->idx == R600_RING_TYPE_DMA_INDEX) | ||
116 | reg = SDMA0_GFX_RB_WPTR + SDMA0_REGISTER_OFFSET; | ||
117 | else | ||
118 | reg = SDMA0_GFX_RB_WPTR + SDMA1_REGISTER_OFFSET; | ||
119 | |||
120 | WREG32(reg, (ring->wptr << 2) & 0x3fffc); | ||
121 | } | ||
122 | |||
123 | /** | ||
55 | * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine | 124 | * cik_sdma_ring_ib_execute - Schedule an IB on the DMA engine |
56 | * | 125 | * |
57 | * @rdev: radeon_device pointer | 126 | * @rdev: radeon_device pointer |
@@ -88,6 +157,35 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev, | |||
88 | } | 157 | } |
89 | 158 | ||
90 | /** | 159 | /** |
160 | * cik_sdma_hdp_flush_ring_emit - emit an hdp flush on the DMA ring | ||
161 | * | ||
162 | * @rdev: radeon_device pointer | ||
163 | * @ridx: radeon ring index | ||
164 | * | ||
165 | * Emit an hdp flush packet on the requested DMA ring. | ||
166 | */ | ||
167 | static void cik_sdma_hdp_flush_ring_emit(struct radeon_device *rdev, | ||
168 | int ridx) | ||
169 | { | ||
170 | struct radeon_ring *ring = &rdev->ring[ridx]; | ||
171 | u32 extra_bits = (SDMA_POLL_REG_MEM_EXTRA_OP(1) | | ||
172 | SDMA_POLL_REG_MEM_EXTRA_FUNC(3)); /* == */ | ||
173 | u32 ref_and_mask; | ||
174 | |||
175 | if (ridx == R600_RING_TYPE_DMA_INDEX) | ||
176 | ref_and_mask = SDMA0; | ||
177 | else | ||
178 | ref_and_mask = SDMA1; | ||
179 | |||
180 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_POLL_REG_MEM, 0, extra_bits)); | ||
181 | radeon_ring_write(ring, GPU_HDP_FLUSH_DONE); | ||
182 | radeon_ring_write(ring, GPU_HDP_FLUSH_REQ); | ||
183 | radeon_ring_write(ring, ref_and_mask); /* reference */ | ||
184 | radeon_ring_write(ring, ref_and_mask); /* mask */ | ||
185 | radeon_ring_write(ring, (0xfff << 16) | 10); /* retry count, poll interval */ | ||
186 | } | ||
187 | |||
188 | /** | ||
91 | * cik_sdma_fence_ring_emit - emit a fence on the DMA ring | 189 | * cik_sdma_fence_ring_emit - emit a fence on the DMA ring |
92 | * | 190 | * |
93 | * @rdev: radeon_device pointer | 191 | * @rdev: radeon_device pointer |
@@ -111,12 +209,7 @@ void cik_sdma_fence_ring_emit(struct radeon_device *rdev, | |||
111 | /* generate an interrupt */ | 209 | /* generate an interrupt */ |
112 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0)); | 210 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_TRAP, 0, 0)); |
113 | /* flush HDP */ | 211 | /* flush HDP */ |
114 | /* We should be using the new POLL_REG_MEM special op packet here | 212 | cik_sdma_hdp_flush_ring_emit(rdev, fence->ring); |
115 | * but it causes sDMA to hang sometimes | ||
116 | */ | ||
117 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | ||
118 | radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); | ||
119 | radeon_ring_write(ring, 0); | ||
120 | } | 213 | } |
121 | 214 | ||
122 | /** | 215 | /** |
@@ -157,7 +250,9 @@ static void cik_sdma_gfx_stop(struct radeon_device *rdev) | |||
157 | u32 rb_cntl, reg_offset; | 250 | u32 rb_cntl, reg_offset; |
158 | int i; | 251 | int i; |
159 | 252 | ||
160 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); | 253 | if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || |
254 | (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) | ||
255 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); | ||
161 | 256 | ||
162 | for (i = 0; i < 2; i++) { | 257 | for (i = 0; i < 2; i++) { |
163 | if (i == 0) | 258 | if (i == 0) |
@@ -288,7 +383,9 @@ static int cik_sdma_gfx_resume(struct radeon_device *rdev) | |||
288 | } | 383 | } |
289 | } | 384 | } |
290 | 385 | ||
291 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | 386 | if ((rdev->asic->copy.copy_ring_index == R600_RING_TYPE_DMA_INDEX) || |
387 | (rdev->asic->copy.copy_ring_index == CAYMAN_RING_TYPE_DMA1_INDEX)) | ||
388 | radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); | ||
292 | 389 | ||
293 | return 0; | 390 | return 0; |
294 | } | 391 | } |
@@ -747,12 +844,7 @@ void cik_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm | |||
747 | radeon_ring_write(ring, VMID(0)); | 844 | radeon_ring_write(ring, VMID(0)); |
748 | 845 | ||
749 | /* flush HDP */ | 846 | /* flush HDP */ |
750 | /* We should be using the new POLL_REG_MEM special op packet here | 847 | cik_sdma_hdp_flush_ring_emit(rdev, ridx); |
751 | * but it causes sDMA to hang sometimes | ||
752 | */ | ||
753 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | ||
754 | radeon_ring_write(ring, HDP_MEM_COHERENCY_FLUSH_CNTL >> 2); | ||
755 | radeon_ring_write(ring, 0); | ||
756 | 848 | ||
757 | /* flush TLB */ | 849 | /* flush TLB */ |
758 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); | 850 | radeon_ring_write(ring, SDMA_PACKET(SDMA_OPCODE_SRBM_WRITE, 0, 0xf000)); |