Hi Michel,
sorry for the super-late reply, i was just catching up with all the
mails and discussions, starting in June, leading to this patch set.
Looks all pretty good.
I'll look at this radeon patch and 2/6 for amdgpu later this week when i
have a fresh brain and enough "obsessive compulsive time", to make sure
all the magic wrt. "virtually extended vblank" and the fudging logic is
fine.
I'll then also run it through my timing tests. I assume the
ati/amdgpu-ddx patches and libdrm patches in your freedesktop home are
all i need for testing?
-mario
On 08/04/2016 05:39 AM, Michel Dänzer wrote:
From: Michel Dänzer
Now we can program a flip during a vertical blank period, if it's the
one targeted by the flip (or a later one). This allows simplifying
radeon_flip_work_func considerably.
Signed-off-by: Michel Dänzer
---
drivers/gpu/drm/radeon/radeon.h | 1 +
drivers/gpu/drm/radeon/radeon_display.c | 89 +
2 files changed, 25 insertions(+), 65 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 5633ee3..1b0dcad 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -742,6 +742,7 @@ struct radeon_flip_work {
struct work_struct unpin_work;
struct radeon_device*rdev;
int crtc_id;
+ u32 target_vblank;
uint64_tbase;
struct drm_pending_vblank_event *event;
struct radeon_bo*old_rbo;
diff --git a/drivers/gpu/drm/radeon/radeon_display.c
b/drivers/gpu/drm/radeon/radeon_display.c
index 5f1cd69..bd9d995 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -400,14 +400,13 @@ static void radeon_flip_work_func(struct work_struct
*__work)
struct radeon_flip_work *work =
container_of(__work, struct radeon_flip_work, flip_work);
struct radeon_device *rdev = work->rdev;
+ struct drm_device *dev = rdev->ddev;
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
struct drm_crtc *crtc = _crtc->base;
unsigned long flags;
int r;
- int vpos, hpos, stat, min_udelay = 0;
- unsigned repcnt = 4;
- struct drm_vblank_crtc *vblank = >dev->vblank[work->crtc_id];
+ int vpos, hpos;
down_read(>exclusive_lock);
if (work->fence) {
@@ -438,59 +437,25 @@ static void radeon_flip_work_func(struct work_struct
*__work)
work->fence = NULL;
}
+ /* Wait until we're out of the vertical blank period before the one
+* targeted by the flip
+*/
+ while (radeon_crtc->enabled &&
+ (radeon_get_crtc_scanoutpos(dev, work->crtc_id, 0,
+ , , NULL, NULL,
+ >hwmode)
+ & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
+ (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
+ (int)(work->target_vblank -
+dev->driver->get_vblank_counter(dev, work->crtc_id)) > 0)
+ usleep_range(1000, 2000);
+
/* We borrow the event spin lock for protecting flip_status */
spin_lock_irqsave(>dev->event_lock, flags);
/* set the proper interrupt */
radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
- /* If this happens to execute within the "virtually extended" vblank
-* interval before the start of the real vblank interval then it needs
-* to delay programming the mmio flip until the real vblank is entered.
-* This prevents completing a flip too early due to the way we fudge
-* our vblank counter and vblank timestamps in order to work around the
-* problem that the hw fires vblank interrupts before actual start of
-* vblank (when line buffer refilling is done for a frame). It
-* complements the fudging logic in radeon_get_crtc_scanoutpos() for
-* timestamping and radeon_get_vblank_counter_kms() for vblank counts.
-*
-* In practice this won't execute very often unless on very fast
-* machines because the time window for this to happen is very small.
-*/
- while (radeon_crtc->enabled && --repcnt) {
- /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank
-* start in hpos, and to the "fudged earlier" vblank start in
-* vpos.
-*/
- stat = radeon_get_crtc_scanoutpos(rdev->ddev, work->crtc_id,
- GET_DISTANCE_TO_VBLANKSTART,
- , , NULL, NULL,
- >hwmode);
-
-