aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu/amdgpu_display.c')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c136
1 files changed, 108 insertions, 28 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 4986340326e2..39fc388f222a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -138,10 +138,52 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
138 kfree(work); 138 kfree(work);
139} 139}
140 140
141int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc, 141
142 struct drm_framebuffer *fb, 142static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work)
143 struct drm_pending_vblank_event *event, 143{
144 uint32_t page_flip_flags, uint32_t target) 144 int i;
145
146 amdgpu_bo_unref(&work->old_abo);
147 dma_fence_put(work->excl);
148 for (i = 0; i < work->shared_count; ++i)
149 dma_fence_put(work->shared[i]);
150 kfree(work->shared);
151 kfree(work);
152}
153
154static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work,
155 struct amdgpu_bo *new_abo)
156{
157 amdgpu_bo_unreserve(new_abo);
158 amdgpu_flip_work_cleanup(work);
159}
160
161static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work,
162 struct amdgpu_bo *new_abo)
163{
164 if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
165 DRM_ERROR("failed to unpin new abo in error path\n");
166 amdgpu_flip_cleanup_unreserve(work, new_abo);
167}
168
169void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
170 struct amdgpu_bo *new_abo)
171{
172 if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) {
173 DRM_ERROR("failed to reserve new abo in error path\n");
174 amdgpu_flip_work_cleanup(work);
175 return;
176 }
177 amdgpu_flip_cleanup_unpin(work, new_abo);
178}
179
180int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
181 struct drm_framebuffer *fb,
182 struct drm_pending_vblank_event *event,
183 uint32_t page_flip_flags,
184 uint32_t target,
185 struct amdgpu_flip_work **work_p,
186 struct amdgpu_bo **new_abo_p)
145{ 187{
146 struct drm_device *dev = crtc->dev; 188 struct drm_device *dev = crtc->dev;
147 struct amdgpu_device *adev = dev->dev_private; 189 struct amdgpu_device *adev = dev->dev_private;
@@ -154,7 +196,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
154 unsigned long flags; 196 unsigned long flags;
155 u64 tiling_flags; 197 u64 tiling_flags;
156 u64 base; 198 u64 base;
157 int i, r; 199 int r;
158 200
159 work = kzalloc(sizeof *work, GFP_KERNEL); 201 work = kzalloc(sizeof *work, GFP_KERNEL);
160 if (work == NULL) 202 if (work == NULL)
@@ -215,41 +257,79 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
215 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 257 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
216 r = -EBUSY; 258 r = -EBUSY;
217 goto pflip_cleanup; 259 goto pflip_cleanup;
260
218 } 261 }
262 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
263
264 *work_p = work;
265 *new_abo_p = new_abo;
266
267 return 0;
268
269pflip_cleanup:
270 amdgpu_crtc_cleanup_flip_ctx(work, new_abo);
271 return r;
272
273unpin:
274 amdgpu_flip_cleanup_unpin(work, new_abo);
275 return r;
276
277unreserve:
278 amdgpu_flip_cleanup_unreserve(work, new_abo);
279 return r;
219 280
281cleanup:
282 amdgpu_flip_work_cleanup(work);
283 return r;
284
285}
286
287void amdgpu_crtc_submit_flip(struct drm_crtc *crtc,
288 struct drm_framebuffer *fb,
289 struct amdgpu_flip_work *work,
290 struct amdgpu_bo *new_abo)
291{
292 unsigned long flags;
293 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
294
295 spin_lock_irqsave(&crtc->dev->event_lock, flags);
220 amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING; 296 amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING;
221 amdgpu_crtc->pflip_works = work; 297 amdgpu_crtc->pflip_works = work;
222 298
223
224 DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
225 amdgpu_crtc->crtc_id, amdgpu_crtc, work);
226 /* update crtc fb */ 299 /* update crtc fb */
227 crtc->primary->fb = fb; 300 crtc->primary->fb = fb;
228 spin_unlock_irqrestore(&crtc->dev->event_lock, flags); 301 spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
302
303 DRM_DEBUG_DRIVER(
304 "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
305 amdgpu_crtc->crtc_id, amdgpu_crtc, work);
306
229 amdgpu_flip_work_func(&work->flip_work.work); 307 amdgpu_flip_work_func(&work->flip_work.work);
230 return 0; 308}
231 309
232pflip_cleanup: 310int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
233 if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) { 311 struct drm_framebuffer *fb,
234 DRM_ERROR("failed to reserve new abo in error path\n"); 312 struct drm_pending_vblank_event *event,
235 goto cleanup; 313 uint32_t page_flip_flags,
236 } 314 uint32_t target)
237unpin: 315{
238 if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) { 316 struct amdgpu_bo *new_abo;
239 DRM_ERROR("failed to unpin new abo in error path\n"); 317 struct amdgpu_flip_work *work;
240 } 318 int r;
241unreserve:
242 amdgpu_bo_unreserve(new_abo);
243 319
244cleanup: 320 r = amdgpu_crtc_prepare_flip(crtc,
245 amdgpu_bo_unref(&work->old_abo); 321 fb,
246 dma_fence_put(work->excl); 322 event,
247 for (i = 0; i < work->shared_count; ++i) 323 page_flip_flags,
248 dma_fence_put(work->shared[i]); 324 target,
249 kfree(work->shared); 325 &work,
250 kfree(work); 326 &new_abo);
327 if (r)
328 return r;
251 329
252 return r; 330 amdgpu_crtc_submit_flip(crtc, fb, work, new_abo);
331
332 return 0;
253} 333}
254 334
255int amdgpu_crtc_set_config(struct drm_mode_set *set) 335int amdgpu_crtc_set_config(struct drm_mode_set *set)