aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMario Kleiner <mario.kleiner.de@gmail.com>2019-03-29 08:00:57 -0400
committerAlex Deucher <alexander.deucher@amd.com>2019-04-03 11:00:33 -0400
commit71bbe51a0839f77fb75b473b23485b026d74ab75 (patch)
treefa64779cacc549c985f3a9a61b85c5f8752b93d9 /drivers/gpu
parentd2574c33bb719575bac7a7044daed24081601804 (diff)
drm/amd/display: Make pageflip event delivery compatible with VRR.
We want vblank counts and timestamps of flip completion as sent in pageflip completion events to be consistent with the vblank count and timestamp of the vblank of flip completion, like in non VRR mode. In VRR mode, drm_update_vblank_count() - and thereby vblank count and timestamp updates - must be delayed until after the end of front-porch of each vblank, as it is only safe to calculate vblank timestamps outside of the front-porch, when we actually know when the vblank will end or has ended. The function drm_update_vblank_count() which updates timestamps and counts gets called by drm_crtc_accurate_vblank_count() or by drm_crtc_handle_vblank(). Therefore we must make sure that pageflip events for a completed flip are only sent out after drm_crtc_accurate_vblank_count() or drm_crtc_handle_vblank() is executed, after end of front-porch for the vblank of flip completion. Two cases: a) Pageflip irq handler executes inside front-porch: In this case we must defer sending pageflip events until drm_crtc_handle_vblank() executes after end of front-porch, and thereby calculates proper vblank count and timestamp. Iow. the pflip irq handler must just arm a pageflip event to be sent out by drm_crtc_handle_vblank() later on. b) Pageflip irq handler executes after end of front-porch, e.g., after flip completion in back-porch or due to a massively delayed handler invocation into the active scanout of the new frame. In this case we can call drm_crtc_accurate_vblank_count() to safely force calculation of a proper vblank count and timestamp, and must send the pageflip completion event ourselves from the pageflip irq handler. This is the same behaviour as needed for standard fixed refresh rate mode. To decide from within pageflip handler if we are in case a) or b), we check the current scanout position against the boundary of front-porch. In non-VRR mode we just do what we did in the past. Signed-off-by: Mario Kleiner <mario.kleiner.de@gmail.com> Reviewed-by: Nicholas Kazlauskas <Nicholas.Kazlauskas@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c68
1 files changed, 55 insertions, 13 deletions
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 3bc3b15121e1..65eb5611a169 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -263,6 +263,10 @@ static void dm_pflip_high_irq(void *interrupt_params)
263 struct common_irq_params *irq_params = interrupt_params; 263 struct common_irq_params *irq_params = interrupt_params;
264 struct amdgpu_device *adev = irq_params->adev; 264 struct amdgpu_device *adev = irq_params->adev;
265 unsigned long flags; 265 unsigned long flags;
266 struct drm_pending_vblank_event *e;
267 struct dm_crtc_state *acrtc_state;
268 uint32_t vpos, hpos, v_blank_start, v_blank_end;
269 bool vrr_active;
266 270
267 amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP); 271 amdgpu_crtc = get_crtc_by_otg_inst(adev, irq_params->irq_src - IRQ_TYPE_PFLIP);
268 272
@@ -285,18 +289,57 @@ static void dm_pflip_high_irq(void *interrupt_params)
285 return; 289 return;
286 } 290 }
287 291
288 /* Update to correct count(s) if racing with vblank irq */ 292 /* page flip completed. */
289 drm_crtc_accurate_vblank_count(&amdgpu_crtc->base); 293 e = amdgpu_crtc->event;
294 amdgpu_crtc->event = NULL;
290 295
291 /* wake up userspace */ 296 if (!e)
292 if (amdgpu_crtc->event) { 297 WARN_ON(1);
293 drm_crtc_send_vblank_event(&amdgpu_crtc->base, amdgpu_crtc->event);
294 298
295 /* page flip completed. clean up */ 299 acrtc_state = to_dm_crtc_state(amdgpu_crtc->base.state);
296 amdgpu_crtc->event = NULL; 300 vrr_active = amdgpu_dm_vrr_active(acrtc_state);
301
302 /* Fixed refresh rate, or VRR scanout position outside front-porch? */
303 if (!vrr_active ||
304 !dc_stream_get_scanoutpos(acrtc_state->stream, &v_blank_start,
305 &v_blank_end, &hpos, &vpos) ||
306 (vpos < v_blank_start)) {
307 /* Update to correct count and vblank timestamp if racing with
308 * vblank irq. This also updates to the correct vblank timestamp
309 * even in VRR mode, as scanout is past the front-porch atm.
310 */
311 drm_crtc_accurate_vblank_count(&amdgpu_crtc->base);
297 312
298 } else 313 /* Wake up userspace by sending the pageflip event with proper
299 WARN_ON(1); 314 * count and timestamp of vblank of flip completion.
315 */
316 if (e) {
317 drm_crtc_send_vblank_event(&amdgpu_crtc->base, e);
318
319 /* Event sent, so done with vblank for this flip */
320 drm_crtc_vblank_put(&amdgpu_crtc->base);
321 }
322 } else if (e) {
323 /* VRR active and inside front-porch: vblank count and
324 * timestamp for pageflip event will only be up to date after
325 * drm_crtc_handle_vblank() has been executed from late vblank
326 * irq handler after start of back-porch (vline 0). We queue the
327 * pageflip event for send-out by drm_crtc_handle_vblank() with
328 * updated timestamp and count, once it runs after us.
329 *
330 * We need to open-code this instead of using the helper
331 * drm_crtc_arm_vblank_event(), as that helper would
332 * call drm_crtc_accurate_vblank_count(), which we must
333 * not call in VRR mode while we are in front-porch!
334 */
335
336 /* sequence will be replaced by real count during send-out. */
337 e->sequence = drm_crtc_vblank_count(&amdgpu_crtc->base);
338 e->pipe = amdgpu_crtc->crtc_id;
339
340 list_add_tail(&e->base.link, &adev->ddev->vblank_event_list);
341 e = NULL;
342 }
300 343
301 /* Keep track of vblank of this flip for flip throttling. We use the 344 /* Keep track of vblank of this flip for flip throttling. We use the
302 * cooked hw counter, as that one incremented at start of this vblank 345 * cooked hw counter, as that one incremented at start of this vblank
@@ -309,10 +352,9 @@ static void dm_pflip_high_irq(void *interrupt_params)
309 amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; 352 amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE;
310 spin_unlock_irqrestore(&adev->ddev->event_lock, flags); 353 spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
311 354
312 DRM_DEBUG_DRIVER("%s - crtc :%d[%p], pflip_stat:AMDGPU_FLIP_NONE\n", 355 DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n",
313 __func__, amdgpu_crtc->crtc_id, amdgpu_crtc); 356 amdgpu_crtc->crtc_id, amdgpu_crtc,
314 357 vrr_active, (int) !e);
315 drm_crtc_vblank_put(&amdgpu_crtc->base);
316} 358}
317 359
318static void dm_vupdate_high_irq(void *interrupt_params) 360static void dm_vupdate_high_irq(void *interrupt_params)