From: Christian König christian.koenig@amd.com
They are doing the same on all generations anyway.
Signed-off-by: Christian König christian.koenig@amd.com --- drivers/gpu/drm/radeon/evergreen.c | 30 ---------------------- drivers/gpu/drm/radeon/r100.c | 30 ---------------------- drivers/gpu/drm/radeon/radeon.h | 4 --- drivers/gpu/drm/radeon/radeon_asic.c | 44 --------------------------------- drivers/gpu/drm/radeon/radeon_asic.h | 6 ----- drivers/gpu/drm/radeon/radeon_display.c | 4 +-- drivers/gpu/drm/radeon/rs600.c | 12 --------- 7 files changed, 2 insertions(+), 128 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b406546..ec31a82 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1301,36 +1301,6 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) }
/** - * radeon_irq_kms_pflip_irq_get - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (evergreen+). - * Enables the pageflip irq (vblank irq). - */ -void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) -{ - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -/** - * evergreen_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (evergreen+). - * Disables the pageflip irq (vblank irq). - */ -void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) -{ - /* disable the pflip int */ - radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - -/** * evergreen_page_flip - pageflip callback. * * @rdev: radeon_device pointer diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index b6c3264..840651f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -142,36 +142,6 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) }
/** - * r100_pre_page_flip - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (r1xx-r4xx). - * Enables the pageflip irq (vblank irq). - */ -void r100_pre_page_flip(struct radeon_device *rdev, int crtc) -{ - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -/** - * r100_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (r1xx-r4xx). - * Disables the pageflip irq (vblank irq). - */ -void r100_post_page_flip(struct radeon_device *rdev, int crtc) -{ - /* disable the pflip int */ - radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - -/** * r100_page_flip - pageflip callback. * * @rdev: radeon_device pointer diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 325f3a5..2b919af 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1881,9 +1881,7 @@ struct radeon_asic { } dpm; /* pageflipping */ struct { - void (*pre_page_flip)(struct radeon_device *rdev, int crtc); u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); - void (*post_page_flip)(struct radeon_device *rdev, int crtc); } pflip; };
@@ -2742,9 +2740,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index ddcd0a2..cb7a0ea 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -248,9 +248,7 @@ static struct radeon_asic r100_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, }, };
@@ -315,9 +313,7 @@ static struct radeon_asic r200_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, }, };
@@ -396,9 +392,7 @@ static struct radeon_asic r300_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, }, };
@@ -463,9 +457,7 @@ static struct radeon_asic r300_asic_pcie = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, }, };
@@ -530,9 +522,7 @@ static struct radeon_asic r420_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, }, };
@@ -597,9 +587,7 @@ static struct radeon_asic rs400_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = { - .pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip, - .post_page_flip = &r100_post_page_flip, }, };
@@ -666,9 +654,7 @@ static struct radeon_asic rs600_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -735,9 +721,7 @@ static struct radeon_asic rs690_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -802,9 +786,7 @@ static struct radeon_asic rv515_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -869,9 +851,7 @@ static struct radeon_asic r520_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -968,9 +948,7 @@ static struct radeon_asic r600_asic = { .get_temperature = &rv6xx_get_temp, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -1059,9 +1037,7 @@ static struct radeon_asic rv6xx_asic = { .force_performance_level = &rv6xx_dpm_force_performance_level, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -1150,9 +1126,7 @@ static struct radeon_asic rs780_asic = { .force_performance_level = &rs780_dpm_force_performance_level, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -1256,9 +1230,7 @@ static struct radeon_asic rv770_asic = { .vblank_too_short = &rv770_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &rs600_pre_page_flip, .page_flip = &rv770_page_flip, - .post_page_flip = &rs600_post_page_flip, }, };
@@ -1375,9 +1347,7 @@ static struct radeon_asic evergreen_asic = { .vblank_too_short = &cypress_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -1467,9 +1437,7 @@ static struct radeon_asic sumo_asic = { .force_performance_level = &sumo_dpm_force_performance_level, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -1560,9 +1528,7 @@ static struct radeon_asic btc_asic = { .vblank_too_short = &btc_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -1704,9 +1670,7 @@ static struct radeon_asic cayman_asic = { .vblank_too_short = &ni_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -1805,9 +1769,7 @@ static struct radeon_asic trinity_asic = { .enable_bapm = &trinity_dpm_enable_bapm, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -1936,9 +1898,7 @@ static struct radeon_asic si_asic = { .vblank_too_short = &ni_dpm_vblank_too_short, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -2099,9 +2059,7 @@ static struct radeon_asic ci_asic = { .powergate_uvd = &ci_dpm_powergate_uvd, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
@@ -2204,9 +2162,7 @@ static struct radeon_asic kv_asic = { .enable_bapm = &kv_dpm_enable_bapm, }, .pflip = { - .pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip, - .post_page_flip = &evergreen_post_page_flip, }, };
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e6455b9..953607d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -135,9 +135,7 @@ extern void r100_pm_prepare(struct radeon_device *rdev); extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_init_profile(struct radeon_device *rdev); extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); -extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
@@ -241,9 +239,7 @@ void rs600_hpd_set_polarity(struct radeon_device *rdev, extern void rs600_pm_misc(struct radeon_device *rdev); extern void rs600_pm_prepare(struct radeon_device *rdev); extern void rs600_pm_finish(struct radeon_device *rdev); -extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); void rs600_set_safe_registers(struct radeon_device *rdev); extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); @@ -520,9 +516,7 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void btc_pm_init_profile(struct radeon_device *rdev); int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); -extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); void evergreen_disable_interrupt_state(struct radeon_device *rdev); int evergreen_mc_wait_for_idle(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8d99d5e..beccc4a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -342,7 +342,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); radeon_fence_unref(&work->fence); - radeon_post_page_flip(work->rdev, work->crtc_id); + radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); schedule_work(&work->work); }
@@ -471,7 +471,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, }
/* set the proper interrupt */ - radeon_pre_page_flip(rdev, radeon_crtc->crtc_id); + radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
return 0;
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 72d3616..e005bd7 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -109,18 +109,6 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) } }
-void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) -{ - /* enable the pflip int */ - radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -void rs600_post_page_flip(struct radeon_device *rdev, int crtc) -{ - /* disable the pflip int */ - radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
From: Christian König christian.koenig@amd.com
We activate the VBLANK irq manually anyway, so this is unnecessary.
Signed-off-by: Christian König christian.koenig@amd.com --- drivers/gpu/drm/radeon/radeon_display.c | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index beccc4a..d597d08 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -340,7 +340,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
- drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); radeon_fence_unref(&work->fence); radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); schedule_work(&work->work); @@ -464,27 +463,11 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, /* update crtc fb */ crtc->primary->fb = fb;
- r = drm_vblank_get(dev, radeon_crtc->crtc_id); - if (r) { - DRM_ERROR("failed to get vblank before flip\n"); - goto pflip_cleanup1; - } - /* set the proper interrupt */ radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
return 0;
-pflip_cleanup1: - if (unlikely(radeon_bo_reserve(rbo, false) != 0)) { - DRM_ERROR("failed to reserve new rbo in error path\n"); - goto pflip_cleanup; - } - if (unlikely(radeon_bo_unpin(rbo) != 0)) { - DRM_ERROR("failed to unpin new rbo in error path\n"); - } - radeon_bo_unreserve(rbo); - pflip_cleanup: spin_lock_irqsave(&dev->event_lock, flags); radeon_crtc->unpin_work = NULL;
On Tue, May 27, 2014 at 10:49 AM, Christian König deathsimple@vodafone.de wrote:
From: Christian König christian.koenig@amd.com
We activate the VBLANK irq manually anyway, so this is unnecessary.
Signed-off-by: Christian König christian.koenig@amd.com
Reviewed-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/radeon_display.c | 17 ----------------- 1 file changed, 17 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index beccc4a..d597d08 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -340,7 +340,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); radeon_fence_unref(&work->fence); radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); schedule_work(&work->work);
@@ -464,27 +463,11 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, /* update crtc fb */ crtc->primary->fb = fb;
r = drm_vblank_get(dev, radeon_crtc->crtc_id);
if (r) {
DRM_ERROR("failed to get vblank before flip\n");
goto pflip_cleanup1;
}
/* set the proper interrupt */ radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); return 0;
-pflip_cleanup1:
if (unlikely(radeon_bo_reserve(rbo, false) != 0)) {
DRM_ERROR("failed to reserve new rbo in error path\n");
goto pflip_cleanup;
}
if (unlikely(radeon_bo_unpin(rbo) != 0)) {
DRM_ERROR("failed to unpin new rbo in error path\n");
}
radeon_bo_unreserve(rbo);
pflip_cleanup: spin_lock_irqsave(&dev->event_lock, flags); radeon_crtc->unpin_work = NULL; -- 1.9.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Christian König christian.koenig@amd.com
Signed-off-by: Christian König christian.koenig@amd.com --- drivers/gpu/drm/radeon/evergreen.c | 18 ++++++++++++++++-- drivers/gpu/drm/radeon/r100.c | 21 ++++++++++++++++++--- drivers/gpu/drm/radeon/radeon.h | 4 +++- drivers/gpu/drm/radeon/radeon_asic.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_asic.h | 15 +++++++++++---- drivers/gpu/drm/radeon/radeon_display.c | 3 ++- drivers/gpu/drm/radeon/rs600.c | 10 ++++++++-- drivers/gpu/drm/radeon/rv770.c | 10 ++++++++-- 8 files changed, 88 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index ec31a82..336f0a5 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1313,7 +1313,7 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) * double buffered update to take place. * Returns the current update pending status. */ -u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -1345,9 +1345,23 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +/** + * evergreen_page_flip_pending - check if page flip is still pending + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to check + * + * Returns the current update pending status. + */ +bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
/* Return current update_pending status: */ - return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING; + return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & + EVERGREEN_GRPH_SURFACE_UPDATE_PENDING); }
/* get temperature in millidegrees */ diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 840651f..52548f7 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -152,9 +152,8 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) * During vblank we take the crtc lock and wait for the update_pending * bit to go high, when it does, we release the lock, and allow the * double buffered update to take place. - * Returns the current update pending status. */ -u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; @@ -176,8 +175,24 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
+} + +/** + * r100_page_flip_pending - check if page flip is still pending + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to check + * + * Check if the last pagefilp is still pending (r1xx-r4xx). + * Returns the current update pending status. + */ +bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + /* Return current update_pending status: */ - return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; + return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & + RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET); }
/** diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 2b919af..4ae304d 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1881,7 +1881,8 @@ struct radeon_asic { } dpm; /* pageflipping */ struct { - u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); + void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base); + bool (*page_flip_pending)(struct radeon_device *rdev, int crtc); } pflip; };
@@ -2741,6 +2742,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index cb7a0ea..d8e1587 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -249,6 +249,7 @@ static struct radeon_asic r100_asic = { }, .pflip = { .page_flip = &r100_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, };
@@ -314,6 +315,7 @@ static struct radeon_asic r200_asic = { }, .pflip = { .page_flip = &r100_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, };
@@ -393,6 +395,7 @@ static struct radeon_asic r300_asic = { }, .pflip = { .page_flip = &r100_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, };
@@ -458,6 +461,7 @@ static struct radeon_asic r300_asic_pcie = { }, .pflip = { .page_flip = &r100_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, };
@@ -523,6 +527,7 @@ static struct radeon_asic r420_asic = { }, .pflip = { .page_flip = &r100_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, };
@@ -588,6 +593,7 @@ static struct radeon_asic rs400_asic = { }, .pflip = { .page_flip = &r100_page_flip, + .page_flip_pending = &r100_page_flip_pending, }, };
@@ -655,6 +661,7 @@ static struct radeon_asic rs600_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -722,6 +729,7 @@ static struct radeon_asic rs690_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -787,6 +795,7 @@ static struct radeon_asic rv515_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -852,6 +861,7 @@ static struct radeon_asic r520_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -949,6 +959,7 @@ static struct radeon_asic r600_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -1038,6 +1049,7 @@ static struct radeon_asic rv6xx_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -1127,6 +1139,7 @@ static struct radeon_asic rs780_asic = { }, .pflip = { .page_flip = &rs600_page_flip, + .page_flip_pending = &rs600_page_flip_pending, }, };
@@ -1231,6 +1244,7 @@ static struct radeon_asic rv770_asic = { }, .pflip = { .page_flip = &rv770_page_flip, + .page_flip_pending = &rv770_page_flip_pending, }, };
@@ -1348,6 +1362,7 @@ static struct radeon_asic evergreen_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -1438,6 +1453,7 @@ static struct radeon_asic sumo_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -1529,6 +1545,7 @@ static struct radeon_asic btc_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -1671,6 +1688,7 @@ static struct radeon_asic cayman_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -1770,6 +1788,7 @@ static struct radeon_asic trinity_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -1899,6 +1918,7 @@ static struct radeon_asic si_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -2060,6 +2080,7 @@ static struct radeon_asic ci_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
@@ -2163,6 +2184,7 @@ static struct radeon_asic kv_asic = { }, .pflip = { .page_flip = &evergreen_page_flip, + .page_flip_pending = &evergreen_page_flip_pending, }, };
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 953607d..0eab015 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -135,7 +135,9 @@ extern void r100_pm_prepare(struct radeon_device *rdev); extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_init_profile(struct radeon_device *rdev); extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); -extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void r100_page_flip(struct radeon_device *rdev, int crtc, + u64 crtc_base); +extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc); extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
@@ -239,7 +241,9 @@ void rs600_hpd_set_polarity(struct radeon_device *rdev, extern void rs600_pm_misc(struct radeon_device *rdev); extern void rs600_pm_prepare(struct radeon_device *rdev); extern void rs600_pm_finish(struct radeon_device *rdev); -extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void rs600_page_flip(struct radeon_device *rdev, int crtc, + u64 crtc_base); +extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc); void rs600_set_safe_registers(struct radeon_device *rdev); extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); @@ -448,7 +452,8 @@ void rv770_fini(struct radeon_device *rdev); int rv770_suspend(struct radeon_device *rdev); int rv770_resume(struct radeon_device *rdev); void rv770_pm_misc(struct radeon_device *rdev); -u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc); void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); void r700_cp_stop(struct radeon_device *rdev); void r700_cp_fini(struct radeon_device *rdev); @@ -516,7 +521,9 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void btc_pm_init_profile(struct radeon_device *rdev); int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); -extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void evergreen_page_flip(struct radeon_device *rdev, int crtc, + u64 crtc_base); +extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc); extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); void evergreen_disable_interrupt_state(struct radeon_device *rdev); int evergreen_mc_wait_for_idle(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d597d08..c52c182 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -294,7 +294,8 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) /* New pageflip, or just completion of a previous one? */ if (!radeon_crtc->deferred_flip_completion) { /* do the flip (mmio) */ - update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base); + radeon_page_flip(rdev, crtc_id, work->new_crtc_base); + update_pending = radeon_page_flip_pending(rdev, crtc_id); } else { /* This is just a completion of a flip queued in crtc * at last invocation. Make sure we go directly to diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index e005bd7..9922ee5 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -109,7 +109,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) } }
-u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -136,9 +136,15 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
/* Return current update_pending status: */ - return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; + return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & + AVIVO_D1GRPH_SURFACE_UPDATE_PENDING); }
void avivo_program_fmt(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index fef3107..97b7766 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -801,7 +801,7 @@ u32 rv770_get_xclk(struct radeon_device *rdev) return reference_clock; }
-u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -835,9 +835,15 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
/* Return current update_pending status: */ - return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING; + return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & + AVIVO_D1GRPH_SURFACE_UPDATE_PENDING); }
/* get temperature in millidegrees */
On Tue, May 27, 2014 at 10:49 AM, Christian König deathsimple@vodafone.de wrote:
From: Christian König christian.koenig@amd.com
Signed-off-by: Christian König christian.koenig@amd.com
Reviewed-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/evergreen.c | 18 ++++++++++++++++-- drivers/gpu/drm/radeon/r100.c | 21 ++++++++++++++++++--- drivers/gpu/drm/radeon/radeon.h | 4 +++- drivers/gpu/drm/radeon/radeon_asic.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_asic.h | 15 +++++++++++---- drivers/gpu/drm/radeon/radeon_display.c | 3 ++- drivers/gpu/drm/radeon/rs600.c | 10 ++++++++-- drivers/gpu/drm/radeon/rv770.c | 10 ++++++++-- 8 files changed, 88 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index ec31a82..336f0a5 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1313,7 +1313,7 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
- double buffered update to take place.
- Returns the current update pending status.
*/ -u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -1345,9 +1345,23 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; WREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +}
+/**
- evergreen_page_flip_pending - check if page flip is still pending
- @rdev: radeon_device pointer
- @crtc_id: crtc to check
- Returns the current update pending status.
- */
+bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; /* Return current update_pending status: */
return RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING;
return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &
EVERGREEN_GRPH_SURFACE_UPDATE_PENDING);
}
/* get temperature in millidegrees */ diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 840651f..52548f7 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -152,9 +152,8 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
- During vblank we take the crtc lock and wait for the update_pending
- bit to go high, when it does, we release the lock, and allow the
- double buffered update to take place.
*/
- Returns the current update pending status.
-u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; @@ -176,8 +175,24 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);
+}
+/**
- r100_page_flip_pending - check if page flip is still pending
- @rdev: radeon_device pointer
- @crtc_id: crtc to check
- Check if the last pagefilp is still pending (r1xx-r4xx).
- Returns the current update pending status.
- */
+bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
/* Return current update_pending status: */
return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET;
return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &
RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);
}
/** diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 2b919af..4ae304d 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1881,7 +1881,8 @@ struct radeon_asic { } dpm; /* pageflipping */ struct {
u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
bool (*page_flip_pending)(struct radeon_device *rdev, int crtc); } pflip;
};
@@ -2741,6 +2742,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) +#define radeon_page_flip_pending(rdev, crtc) (rdev)->asic->pflip.page_flip_pending((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index cb7a0ea..d8e1587 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -249,6 +249,7 @@ static struct radeon_asic r100_asic = { }, .pflip = { .page_flip = &r100_page_flip,
.page_flip_pending = &r100_page_flip_pending, },
};
@@ -314,6 +315,7 @@ static struct radeon_asic r200_asic = { }, .pflip = { .page_flip = &r100_page_flip,
.page_flip_pending = &r100_page_flip_pending, },
};
@@ -393,6 +395,7 @@ static struct radeon_asic r300_asic = { }, .pflip = { .page_flip = &r100_page_flip,
.page_flip_pending = &r100_page_flip_pending, },
};
@@ -458,6 +461,7 @@ static struct radeon_asic r300_asic_pcie = { }, .pflip = { .page_flip = &r100_page_flip,
.page_flip_pending = &r100_page_flip_pending, },
};
@@ -523,6 +527,7 @@ static struct radeon_asic r420_asic = { }, .pflip = { .page_flip = &r100_page_flip,
.page_flip_pending = &r100_page_flip_pending, },
};
@@ -588,6 +593,7 @@ static struct radeon_asic rs400_asic = { }, .pflip = { .page_flip = &r100_page_flip,
.page_flip_pending = &r100_page_flip_pending, },
};
@@ -655,6 +661,7 @@ static struct radeon_asic rs600_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -722,6 +729,7 @@ static struct radeon_asic rs690_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -787,6 +795,7 @@ static struct radeon_asic rv515_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -852,6 +861,7 @@ static struct radeon_asic r520_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -949,6 +959,7 @@ static struct radeon_asic r600_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -1038,6 +1049,7 @@ static struct radeon_asic rv6xx_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -1127,6 +1139,7 @@ static struct radeon_asic rs780_asic = { }, .pflip = { .page_flip = &rs600_page_flip,
.page_flip_pending = &rs600_page_flip_pending, },
};
@@ -1231,6 +1244,7 @@ static struct radeon_asic rv770_asic = { }, .pflip = { .page_flip = &rv770_page_flip,
.page_flip_pending = &rv770_page_flip_pending, },
};
@@ -1348,6 +1362,7 @@ static struct radeon_asic evergreen_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -1438,6 +1453,7 @@ static struct radeon_asic sumo_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -1529,6 +1545,7 @@ static struct radeon_asic btc_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -1671,6 +1688,7 @@ static struct radeon_asic cayman_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -1770,6 +1788,7 @@ static struct radeon_asic trinity_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -1899,6 +1918,7 @@ static struct radeon_asic si_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -2060,6 +2080,7 @@ static struct radeon_asic ci_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
@@ -2163,6 +2184,7 @@ static struct radeon_asic kv_asic = { }, .pflip = { .page_flip = &evergreen_page_flip,
.page_flip_pending = &evergreen_page_flip_pending, },
};
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 953607d..0eab015 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -135,7 +135,9 @@ extern void r100_pm_prepare(struct radeon_device *rdev); extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_init_profile(struct radeon_device *rdev); extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); -extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void r100_page_flip(struct radeon_device *rdev, int crtc,
u64 crtc_base);
+extern bool r100_page_flip_pending(struct radeon_device *rdev, int crtc); extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
@@ -239,7 +241,9 @@ void rs600_hpd_set_polarity(struct radeon_device *rdev, extern void rs600_pm_misc(struct radeon_device *rdev); extern void rs600_pm_prepare(struct radeon_device *rdev); extern void rs600_pm_finish(struct radeon_device *rdev); -extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void rs600_page_flip(struct radeon_device *rdev, int crtc,
u64 crtc_base);
+extern bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc); void rs600_set_safe_registers(struct radeon_device *rdev); extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); @@ -448,7 +452,8 @@ void rv770_fini(struct radeon_device *rdev); int rv770_suspend(struct radeon_device *rdev); int rv770_resume(struct radeon_device *rdev); void rv770_pm_misc(struct radeon_device *rdev); -u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +void rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc); void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc); void r700_cp_stop(struct radeon_device *rdev); void r700_cp_fini(struct radeon_device *rdev); @@ -516,7 +521,9 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void btc_pm_init_profile(struct radeon_device *rdev); int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); -extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); +extern void evergreen_page_flip(struct radeon_device *rdev, int crtc,
u64 crtc_base);
+extern bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc); extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); void evergreen_disable_interrupt_state(struct radeon_device *rdev); int evergreen_mc_wait_for_idle(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d597d08..c52c182 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -294,7 +294,8 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) /* New pageflip, or just completion of a previous one? */ if (!radeon_crtc->deferred_flip_completion) { /* do the flip (mmio) */
update_pending = radeon_page_flip(rdev, crtc_id, work->new_crtc_base);
radeon_page_flip(rdev, crtc_id, work->new_crtc_base);
update_pending = radeon_page_flip_pending(rdev, crtc_id); } else { /* This is just a completion of a flip queued in crtc * at last invocation. Make sure we go directly to
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index e005bd7..9922ee5 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -109,7 +109,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) } }
-u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -136,9 +136,15 @@ u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +}
+bool rs600_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; /* Return current update_pending status: */
return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING;
return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
}
void avivo_program_fmt(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index fef3107..97b7766 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -801,7 +801,7 @@ u32 rv770_get_xclk(struct radeon_device *rdev) return reference_clock; }
-u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); @@ -835,9 +835,15 @@ u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) /* Unlock the lock, so double-buffering can take place inside vblank */ tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +}
+bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; /* Return current update_pending status: */
return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING;
return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) &
AVIVO_D1GRPH_SURFACE_UPDATE_PENDING);
}
/* get temperature in millidegrees */
1.9.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Christian König christian.koenig@amd.com
Signed-off-by: Christian König christian.koenig@amd.com --- drivers/gpu/drm/radeon/cik.c | 12 ++++++------ drivers/gpu/drm/radeon/evergreen.c | 12 ++++++------ drivers/gpu/drm/radeon/r100.c | 4 ++-- drivers/gpu/drm/radeon/r600.c | 4 ++-- drivers/gpu/drm/radeon/radeon_display.c | 33 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/radeon_mode.h | 1 + drivers/gpu/drm/radeon/rs600.c | 4 ++-- drivers/gpu/drm/radeon/si.c | 12 ++++++------ 8 files changed, 56 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 8d0f177..a518140 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7314,7 +7314,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -7340,7 +7340,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } @@ -7366,7 +7366,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_flip(rdev, 2); + radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } @@ -7392,7 +7392,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_flip(rdev, 3); + radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } @@ -7418,7 +7418,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_flip(rdev, 4); + radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } @@ -7444,7 +7444,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_flip(rdev, 5); + radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 336f0a5..0318230 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4789,7 +4789,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -4815,7 +4815,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } @@ -4841,7 +4841,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_flip(rdev, 2); + radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } @@ -4867,7 +4867,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_flip(rdev, 3); + radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } @@ -4893,7 +4893,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_flip(rdev, 4); + radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } @@ -4919,7 +4919,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_flip(rdev, 5); + radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 52548f7..ad99813 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -779,7 +779,7 @@ int r100_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); } if (status & RADEON_CRTC2_VBLANK_STAT) { if (rdev->irq.crtc_vblank_int[1]) { @@ -788,7 +788,7 @@ int r100_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); } if (status & RADEON_FP_DETECT_STAT) { queue_hotplug = true; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6e887d0..436e550 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3876,7 +3876,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -3902,7 +3902,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index c52c182..88e3cbe 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -276,7 +276,7 @@ static void radeon_unpin_work_func(struct work_struct *__work) kfree(work); }
-void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_unpin_work *work; @@ -302,7 +302,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) * completion routine. */ update_pending = 0; - radeon_crtc->deferred_flip_completion = 0; }
/* Has the pageflip already completed in crtc, or is it certain @@ -330,10 +329,40 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) radeon_crtc->deferred_flip_completion = 1; spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; + } else { + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + radeon_crtc_handle_flip(rdev, crtc_id); + } +} + +/** + * radeon_crtc_handle_flip - page flip completed + * + * @rdev: radeon device pointer + * @crtc_id: crtc number this event is for + * + * Called when we are sure that a page flip for this crtc is completed. + */ +void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +{ + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + struct radeon_unpin_work *work; + unsigned long flags; + + /* this can happen at init */ + if (radeon_crtc == NULL) + return; + + spin_lock_irqsave(&rdev->ddev->event_lock, flags); + work = radeon_crtc->unpin_work; + if (work == NULL) { + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + return; }
/* Pageflip (will be) certainly completed in this vblank. Clean up. */ radeon_crtc->unpin_work = NULL; + radeon_crtc->deferred_flip_completion = 0;
/* wakeup userspace */ if (work->event) diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index b265a8b..718be1a 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -907,6 +907,7 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
void radeon_fb_output_poll_changed(struct radeon_device *rdev);
+void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id); void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 9922ee5..dd12dc2 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -781,7 +781,7 @@ int rs600_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); } if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { if (rdev->irq.crtc_vblank_int[1]) { @@ -790,7 +790,7 @@ int rs600_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); } if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { queue_hotplug = true; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 9739d71..5c1c0c7 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6150,7 +6150,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0])) - radeon_crtc_handle_flip(rdev, 0); + radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); } @@ -6176,7 +6176,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1])) - radeon_crtc_handle_flip(rdev, 1); + radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); } @@ -6202,7 +6202,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2])) - radeon_crtc_handle_flip(rdev, 2); + radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); } @@ -6228,7 +6228,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3])) - radeon_crtc_handle_flip(rdev, 3); + radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); } @@ -6254,7 +6254,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4])) - radeon_crtc_handle_flip(rdev, 4); + radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); } @@ -6280,7 +6280,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5])) - radeon_crtc_handle_flip(rdev, 5); + radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); }
On Tue, May 27, 2014 at 10:49 AM, Christian König deathsimple@vodafone.de wrote:
From: Christian König christian.koenig@amd.com
Signed-off-by: Christian König christian.koenig@amd.com
Reviewed-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/cik.c | 12 ++++++------ drivers/gpu/drm/radeon/evergreen.c | 12 ++++++------ drivers/gpu/drm/radeon/r100.c | 4 ++-- drivers/gpu/drm/radeon/r600.c | 4 ++-- drivers/gpu/drm/radeon/radeon_display.c | 33 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/radeon/radeon_mode.h | 1 + drivers/gpu/drm/radeon/rs600.c | 4 ++-- drivers/gpu/drm/radeon/si.c | 12 ++++++------ 8 files changed, 56 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 8d0f177..a518140 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -7314,7 +7314,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0]))
radeon_crtc_handle_flip(rdev, 0);
radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.cik.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); }
@@ -7340,7 +7340,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1]))
radeon_crtc_handle_flip(rdev, 1);
radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.cik.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); }
@@ -7366,7 +7366,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2]))
radeon_crtc_handle_flip(rdev, 2);
radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.cik.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); }
@@ -7392,7 +7392,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3]))
radeon_crtc_handle_flip(rdev, 3);
radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.cik.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); }
@@ -7418,7 +7418,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4]))
radeon_crtc_handle_flip(rdev, 4);
radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.cik.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); }
@@ -7444,7 +7444,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5]))
radeon_crtc_handle_flip(rdev, 5);
radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.cik.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); }
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 336f0a5..0318230 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -4789,7 +4789,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0]))
radeon_crtc_handle_flip(rdev, 0);
radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); }
@@ -4815,7 +4815,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1]))
radeon_crtc_handle_flip(rdev, 1);
radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); }
@@ -4841,7 +4841,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2]))
radeon_crtc_handle_flip(rdev, 2);
radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); }
@@ -4867,7 +4867,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3]))
radeon_crtc_handle_flip(rdev, 3);
radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); }
@@ -4893,7 +4893,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4]))
radeon_crtc_handle_flip(rdev, 4);
radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); }
@@ -4919,7 +4919,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5]))
radeon_crtc_handle_flip(rdev, 5);
radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); }
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 52548f7..ad99813 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -779,7 +779,7 @@ int r100_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0]))
radeon_crtc_handle_flip(rdev, 0);
radeon_crtc_handle_vblank(rdev, 0); } if (status & RADEON_CRTC2_VBLANK_STAT) { if (rdev->irq.crtc_vblank_int[1]) {
@@ -788,7 +788,7 @@ int r100_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1]))
radeon_crtc_handle_flip(rdev, 1);
radeon_crtc_handle_vblank(rdev, 1); } if (status & RADEON_FP_DETECT_STAT) { queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6e887d0..436e550 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -3876,7 +3876,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0]))
radeon_crtc_handle_flip(rdev, 0);
radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); }
@@ -3902,7 +3902,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1]))
radeon_crtc_handle_flip(rdev, 1);
radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); }
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index c52c182..88e3cbe 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -276,7 +276,7 @@ static void radeon_unpin_work_func(struct work_struct *__work) kfree(work); }
-void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_unpin_work *work; @@ -302,7 +302,6 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) * completion routine. */ update_pending = 0;
radeon_crtc->deferred_flip_completion = 0; } /* Has the pageflip already completed in crtc, or is it certain
@@ -330,10 +329,40 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) radeon_crtc->deferred_flip_completion = 1; spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return;
} else {
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
radeon_crtc_handle_flip(rdev, crtc_id);
}
+}
+/**
- radeon_crtc_handle_flip - page flip completed
- @rdev: radeon device pointer
- @crtc_id: crtc number this event is for
- Called when we are sure that a page flip for this crtc is completed.
- */
+void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) +{
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
struct radeon_unpin_work *work;
unsigned long flags;
/* this can happen at init */
if (radeon_crtc == NULL)
return;
spin_lock_irqsave(&rdev->ddev->event_lock, flags);
work = radeon_crtc->unpin_work;
if (work == NULL) {
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
return; } /* Pageflip (will be) certainly completed in this vblank. Clean up. */ radeon_crtc->unpin_work = NULL;
radeon_crtc->deferred_flip_completion = 0; /* wakeup userspace */ if (work->event)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index b265a8b..718be1a 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -907,6 +907,7 @@ bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
void radeon_fb_output_poll_changed(struct radeon_device *rdev);
+void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id); void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled); diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 9922ee5..dd12dc2 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -781,7 +781,7 @@ int rs600_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0]))
radeon_crtc_handle_flip(rdev, 0);
radeon_crtc_handle_vblank(rdev, 0); } if (G_007EDC_LB_D2_VBLANK_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { if (rdev->irq.crtc_vblank_int[1]) {
@@ -790,7 +790,7 @@ int rs600_irq_process(struct radeon_device *rdev) wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1]))
radeon_crtc_handle_flip(rdev, 1);
radeon_crtc_handle_vblank(rdev, 1); } if (G_007EDC_DC_HOT_PLUG_DETECT1_INTERRUPT(rdev->irq.stat_regs.r500.disp_int)) { queue_hotplug = true;
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 9739d71..5c1c0c7 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -6150,7 +6150,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[0]))
radeon_crtc_handle_flip(rdev, 0);
radeon_crtc_handle_vblank(rdev, 0); rdev->irq.stat_regs.evergreen.disp_int &= ~LB_D1_VBLANK_INTERRUPT; DRM_DEBUG("IH: D1 vblank\n"); }
@@ -6176,7 +6176,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[1]))
radeon_crtc_handle_flip(rdev, 1);
radeon_crtc_handle_vblank(rdev, 1); rdev->irq.stat_regs.evergreen.disp_int_cont &= ~LB_D2_VBLANK_INTERRUPT; DRM_DEBUG("IH: D2 vblank\n"); }
@@ -6202,7 +6202,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[2]))
radeon_crtc_handle_flip(rdev, 2);
radeon_crtc_handle_vblank(rdev, 2); rdev->irq.stat_regs.evergreen.disp_int_cont2 &= ~LB_D3_VBLANK_INTERRUPT; DRM_DEBUG("IH: D3 vblank\n"); }
@@ -6228,7 +6228,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[3]))
radeon_crtc_handle_flip(rdev, 3);
radeon_crtc_handle_vblank(rdev, 3); rdev->irq.stat_regs.evergreen.disp_int_cont3 &= ~LB_D4_VBLANK_INTERRUPT; DRM_DEBUG("IH: D4 vblank\n"); }
@@ -6254,7 +6254,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[4]))
radeon_crtc_handle_flip(rdev, 4);
radeon_crtc_handle_vblank(rdev, 4); rdev->irq.stat_regs.evergreen.disp_int_cont4 &= ~LB_D5_VBLANK_INTERRUPT; DRM_DEBUG("IH: D5 vblank\n"); }
@@ -6280,7 +6280,7 @@ restart_ih: wake_up(&rdev->irq.vblank_queue); } if (atomic_read(&rdev->irq.pflip[5]))
radeon_crtc_handle_flip(rdev, 5);
radeon_crtc_handle_vblank(rdev, 5); rdev->irq.stat_regs.evergreen.disp_int_cont5 &= ~LB_D6_VBLANK_INTERRUPT; DRM_DEBUG("IH: D6 vblank\n"); }
-- 1.9.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Christian König christian.koenig@amd.com
Instead of trying to flip inside the vblank period when the buffer is idle, offload blocking for idle to a kernel thread and program the flip directly into the hardware.
v2: add error handling, fix EBUSY handling v3: add proper exclusive_lock handling
Signed-off-by: Christian König christian.koenig@amd.com --- drivers/gpu/drm/radeon/radeon.h | 16 ++- drivers/gpu/drm/radeon/radeon_display.c | 245 ++++++++++++++++++-------------- drivers/gpu/drm/radeon/radeon_mode.h | 4 +- 3 files changed, 150 insertions(+), 115 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4ae304d..736bfa2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -676,14 +676,16 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell); * IRQS. */
-struct radeon_unpin_work { - struct work_struct work; - struct radeon_device *rdev; - int crtc_id; - struct radeon_fence *fence; +struct radeon_flip_work { + struct work_struct flip_work; + struct work_struct unpin_work; + struct radeon_device *rdev; + int crtc_id; + struct drm_framebuffer *fb; struct drm_pending_vblank_event *event; - struct radeon_bo *old_rbo; - u64 new_crtc_base; + struct radeon_bo *old_rbo; + struct radeon_bo *new_rbo; + struct radeon_fence *fence; };
struct r500_irq_stat_regs { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 88e3cbe..6b3de5c 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -249,16 +249,21 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
drm_crtc_cleanup(crtc); + destroy_workqueue(radeon_crtc->flip_queue); kfree(radeon_crtc); }
-/* - * Handle unpin events outside the interrupt handler proper. +/** + * radeon_unpin_work_func - unpin old buffer object + * + * @__work - kernel work item + * + * Unpin the old frame buffer object outside of the interrupt handler */ static void radeon_unpin_work_func(struct work_struct *__work) { - struct radeon_unpin_work *work = - container_of(__work, struct radeon_unpin_work, work); + struct radeon_flip_work *work = + container_of(__work, struct radeon_flip_work, unpin_work); int r;
/* unpin of the old buffer */ @@ -279,30 +284,19 @@ static void radeon_unpin_work_func(struct work_struct *__work) void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; - struct radeon_unpin_work *work; + struct radeon_flip_work *work; unsigned long flags; u32 update_pending; int vpos, hpos;
spin_lock_irqsave(&rdev->ddev->event_lock, flags); - work = radeon_crtc->unpin_work; - if (work == NULL || - (work->fence && !radeon_fence_signaled(work->fence))) { + work = radeon_crtc->flip_work; + if (work == NULL) { spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; } - /* New pageflip, or just completion of a previous one? */ - if (!radeon_crtc->deferred_flip_completion) { - /* do the flip (mmio) */ - radeon_page_flip(rdev, crtc_id, work->new_crtc_base); - update_pending = radeon_page_flip_pending(rdev, crtc_id); - } else { - /* This is just a completion of a flip queued in crtc - * at last invocation. Make sure we go directly to - * completion routine. - */ - update_pending = 0; - } + + update_pending = radeon_page_flip_pending(rdev, crtc_id);
/* Has the pageflip already completed in crtc, or is it certain * to complete in this vblank? @@ -320,19 +314,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) */ update_pending = 0; } - if (update_pending) { - /* crtc didn't flip in this target vblank interval, - * but flip is pending in crtc. It will complete it - * in next vblank interval, so complete the flip at - * next vblank irq. - */ - radeon_crtc->deferred_flip_completion = 1; - spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); - return; - } else { - spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); + if (!update_pending) radeon_crtc_handle_flip(rdev, crtc_id); - } }
/** @@ -346,7 +330,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; - struct radeon_unpin_work *work; + struct radeon_flip_work *work; unsigned long flags;
/* this can happen at init */ @@ -354,15 +338,14 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) return;
spin_lock_irqsave(&rdev->ddev->event_lock, flags); - work = radeon_crtc->unpin_work; + work = radeon_crtc->flip_work; if (work == NULL) { spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; }
- /* Pageflip (will be) certainly completed in this vblank. Clean up. */ - radeon_crtc->unpin_work = NULL; - radeon_crtc->deferred_flip_completion = 0; + /* Pageflip completed. Clean up. */ + radeon_crtc->flip_work = NULL;
/* wakeup userspace */ if (work->event) @@ -372,83 +355,69 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
radeon_fence_unref(&work->fence); radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); - schedule_work(&work->work); + queue_work(radeon_crtc->flip_queue, &work->unpin_work); }
-static int radeon_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags) +/** + * radeon_flip_work_func - page flip framebuffer + * + * @work - kernel work item + * + * Wait for the buffer object to become idle and do the actual page flip + */ +static void radeon_flip_work_func(struct work_struct *__work) { - struct drm_device *dev = crtc->dev; - struct radeon_device *rdev = dev->dev_private; - struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); - struct radeon_framebuffer *old_radeon_fb; - struct radeon_framebuffer *new_radeon_fb; - struct drm_gem_object *obj; - struct radeon_bo *rbo; - struct radeon_unpin_work *work; - unsigned long flags; - u32 tiling_flags, pitch_pixels; - u64 base; - int r; + struct radeon_flip_work *work = + container_of(__work, struct radeon_flip_work, flip_work); + struct radeon_device *rdev = work->rdev; + struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
- work = kzalloc(sizeof *work, GFP_KERNEL); - if (work == NULL) - return -ENOMEM; + struct drm_crtc *crtc = &radeon_crtc->base; + struct drm_framebuffer *fb = work->fb;
- work->event = event; - work->rdev = rdev; - work->crtc_id = radeon_crtc->crtc_id; - old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); - new_radeon_fb = to_radeon_framebuffer(fb); - /* schedule unpin of the old buffer */ - obj = old_radeon_fb->obj; - /* take a reference to the old object */ - drm_gem_object_reference(obj); - rbo = gem_to_radeon_bo(obj); - work->old_rbo = rbo; - obj = new_radeon_fb->obj; - rbo = gem_to_radeon_bo(obj); + uint32_t tiling_flags, pitch_pixels; + uint64_t base;
- spin_lock(&rbo->tbo.bdev->fence_lock); - if (rbo->tbo.sync_obj) - work->fence = radeon_fence_ref(rbo->tbo.sync_obj); - spin_unlock(&rbo->tbo.bdev->fence_lock); + unsigned long flags; + int r;
- INIT_WORK(&work->work, radeon_unpin_work_func); + down_read(&rdev->exclusive_lock); + while (work->fence) { + r = radeon_fence_wait(work->fence, false); + if (r == -EDEADLK) { + up_read(&rdev->exclusive_lock); + r = radeon_gpu_reset(rdev); + down_read(&rdev->exclusive_lock); + }
- /* We borrow the event spin lock for protecting unpin_work */ - spin_lock_irqsave(&dev->event_lock, flags); - if (radeon_crtc->unpin_work) { - DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); - r = -EBUSY; - goto unlock_free; + if (r) { + DRM_ERROR("failed to wait on page flip fence (%d)!\n", + r); + goto cleanup; + } else + radeon_fence_unref(&work->fence); } - radeon_crtc->unpin_work = work; - radeon_crtc->deferred_flip_completion = 0; - spin_unlock_irqrestore(&dev->event_lock, flags);
/* pin the new buffer */ DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", - work->old_rbo, rbo); + work->old_rbo, work->new_rbo);
- r = radeon_bo_reserve(rbo, false); + r = radeon_bo_reserve(work->new_rbo, false); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve new rbo buffer before flip\n"); - goto pflip_cleanup; + goto cleanup; } /* Only 27 bit offset for legacy CRTC */ - r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, + r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM, ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); if (unlikely(r != 0)) { - radeon_bo_unreserve(rbo); + radeon_bo_unreserve(work->new_rbo); r = -EINVAL; DRM_ERROR("failed to pin new rbo buffer before flip\n"); - goto pflip_cleanup; + goto cleanup; } - radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); - radeon_bo_unreserve(rbo); + radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL); + radeon_bo_unreserve(work->new_rbo);
if (!ASIC_IS_AVIVO(rdev)) { /* crtc offset is from display base addr not FB location */ @@ -486,28 +455,91 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, base &= ~7; }
- spin_lock_irqsave(&dev->event_lock, flags); - work->new_crtc_base = base; - spin_unlock_irqrestore(&dev->event_lock, flags); - - /* update crtc fb */ - crtc->primary->fb = fb; + /* We borrow the event spin lock for protecting flip_work */ + spin_lock_irqsave(&crtc->dev->event_lock, flags);
/* set the proper interrupt */ radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
- return 0; + /* do the flip (mmio) */ + radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
-pflip_cleanup: - spin_lock_irqsave(&dev->event_lock, flags); - radeon_crtc->unpin_work = NULL; -unlock_free: - spin_unlock_irqrestore(&dev->event_lock, flags); - drm_gem_object_unreference_unlocked(old_radeon_fb->obj); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + up_read(&rdev->exclusive_lock); + + return; + +cleanup: + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); radeon_fence_unref(&work->fence); kfree(work); + up_read(&rdev->exclusive_lock); +} + +static int radeon_crtc_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t page_flip_flags) +{ + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_framebuffer *old_radeon_fb; + struct radeon_framebuffer *new_radeon_fb; + struct drm_gem_object *obj; + struct radeon_flip_work *work; + unsigned long flags; + + work = kzalloc(sizeof *work, GFP_KERNEL); + if (work == NULL) + return -ENOMEM; + + INIT_WORK(&work->flip_work, radeon_flip_work_func); + INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
- return r; + work->rdev = rdev; + work->crtc_id = radeon_crtc->crtc_id; + work->fb = fb; + work->event = event; + + /* schedule unpin of the old buffer */ + old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); + obj = old_radeon_fb->obj; + + /* take a reference to the old object */ + drm_gem_object_reference(obj); + work->old_rbo = gem_to_radeon_bo(obj); + + new_radeon_fb = to_radeon_framebuffer(fb); + obj = new_radeon_fb->obj; + work->new_rbo = gem_to_radeon_bo(obj); + + spin_lock(&work->new_rbo->tbo.bdev->fence_lock); + if (work->new_rbo->tbo.sync_obj) + work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj); + spin_unlock(&work->new_rbo->tbo.bdev->fence_lock); + + /* update crtc fb */ + crtc->primary->fb = fb; + + /* We borrow the event spin lock for protecting flip_work */ + spin_lock_irqsave(&crtc->dev->event_lock, flags); + + if (radeon_crtc->flip_work) { + DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); + radeon_fence_unref(&work->fence); + kfree(work); + return -EBUSY; + } + radeon_crtc->flip_work = work; + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + queue_work(radeon_crtc->flip_queue, &work->flip_work); + + return 0; }
static int @@ -577,6 +609,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index; + radeon_crtc->flip_queue = create_singlethread_workqueue("radeon-crtc"); rdev->mode_info.crtcs[index] = radeon_crtc;
if (rdev->family >= CHIP_BONAIRE) { diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 718be1a..ea72ad8 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -325,8 +325,8 @@ struct radeon_crtc { struct drm_display_mode native_mode; int pll_id; /* page flipping */ - struct radeon_unpin_work *unpin_work; - int deferred_flip_completion; + struct workqueue_struct *flip_queue; + struct radeon_flip_work *flip_work; /* pll sharing */ struct radeon_atom_ss ss; bool ss_enabled;
On Tue, May 27, 2014 at 10:49 AM, Christian König deathsimple@vodafone.de wrote:
From: Christian König christian.koenig@amd.com
Instead of trying to flip inside the vblank period when the buffer is idle, offload blocking for idle to a kernel thread and program the flip directly into the hardware.
v2: add error handling, fix EBUSY handling v3: add proper exclusive_lock handling
Signed-off-by: Christian König christian.koenig@amd.com
Reviewed-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/radeon.h | 16 ++- drivers/gpu/drm/radeon/radeon_display.c | 245 ++++++++++++++++++-------------- drivers/gpu/drm/radeon/radeon_mode.h | 4 +- 3 files changed, 150 insertions(+), 115 deletions(-)
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4ae304d..736bfa2 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -676,14 +676,16 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell);
- IRQS.
*/
-struct radeon_unpin_work {
struct work_struct work;
struct radeon_device *rdev;
int crtc_id;
struct radeon_fence *fence;
+struct radeon_flip_work {
struct work_struct flip_work;
struct work_struct unpin_work;
struct radeon_device *rdev;
int crtc_id;
struct drm_framebuffer *fb; struct drm_pending_vblank_event *event;
struct radeon_bo *old_rbo;
u64 new_crtc_base;
struct radeon_bo *old_rbo;
struct radeon_bo *new_rbo;
struct radeon_fence *fence;
};
struct r500_irq_stat_regs { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 88e3cbe..6b3de5c 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -249,16 +249,21 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
drm_crtc_cleanup(crtc);
destroy_workqueue(radeon_crtc->flip_queue); kfree(radeon_crtc);
}
-/*
- Handle unpin events outside the interrupt handler proper.
+/**
- radeon_unpin_work_func - unpin old buffer object
- @__work - kernel work item
*/
- Unpin the old frame buffer object outside of the interrupt handler
static void radeon_unpin_work_func(struct work_struct *__work) {
struct radeon_unpin_work *work =
container_of(__work, struct radeon_unpin_work, work);
struct radeon_flip_work *work =
container_of(__work, struct radeon_flip_work, unpin_work); int r; /* unpin of the old buffer */
@@ -279,30 +284,19 @@ static void radeon_unpin_work_func(struct work_struct *__work) void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
struct radeon_unpin_work *work;
struct radeon_flip_work *work; unsigned long flags; u32 update_pending; int vpos, hpos; spin_lock_irqsave(&rdev->ddev->event_lock, flags);
work = radeon_crtc->unpin_work;
if (work == NULL ||
(work->fence && !radeon_fence_signaled(work->fence))) {
work = radeon_crtc->flip_work;
if (work == NULL) { spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; }
/* New pageflip, or just completion of a previous one? */
if (!radeon_crtc->deferred_flip_completion) {
/* do the flip (mmio) */
radeon_page_flip(rdev, crtc_id, work->new_crtc_base);
update_pending = radeon_page_flip_pending(rdev, crtc_id);
} else {
/* This is just a completion of a flip queued in crtc
* at last invocation. Make sure we go directly to
* completion routine.
*/
update_pending = 0;
}
update_pending = radeon_page_flip_pending(rdev, crtc_id); /* Has the pageflip already completed in crtc, or is it certain * to complete in this vblank?
@@ -320,19 +314,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) */ update_pending = 0; }
if (update_pending) {
/* crtc didn't flip in this target vblank interval,
* but flip is pending in crtc. It will complete it
* in next vblank interval, so complete the flip at
* next vblank irq.
*/
radeon_crtc->deferred_flip_completion = 1;
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
return;
} else {
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
spin_unlock_irqrestore(&rdev->ddev->event_lock, flags);
if (!update_pending) radeon_crtc_handle_flip(rdev, crtc_id);
}
}
/** @@ -346,7 +330,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
struct radeon_unpin_work *work;
struct radeon_flip_work *work; unsigned long flags; /* this can happen at init */
@@ -354,15 +338,14 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) return;
spin_lock_irqsave(&rdev->ddev->event_lock, flags);
work = radeon_crtc->unpin_work;
work = radeon_crtc->flip_work; if (work == NULL) { spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); return; }
/* Pageflip (will be) certainly completed in this vblank. Clean up. */
radeon_crtc->unpin_work = NULL;
radeon_crtc->deferred_flip_completion = 0;
/* Pageflip completed. Clean up. */
radeon_crtc->flip_work = NULL; /* wakeup userspace */ if (work->event)
@@ -372,83 +355,69 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
radeon_fence_unref(&work->fence); radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id);
schedule_work(&work->work);
queue_work(radeon_crtc->flip_queue, &work->unpin_work);
}
-static int radeon_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags)
+/**
- radeon_flip_work_func - page flip framebuffer
- @work - kernel work item
- Wait for the buffer object to become idle and do the actual page flip
- */
+static void radeon_flip_work_func(struct work_struct *__work) {
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_framebuffer *old_radeon_fb;
struct radeon_framebuffer *new_radeon_fb;
struct drm_gem_object *obj;
struct radeon_bo *rbo;
struct radeon_unpin_work *work;
unsigned long flags;
u32 tiling_flags, pitch_pixels;
u64 base;
int r;
struct radeon_flip_work *work =
container_of(__work, struct radeon_flip_work, flip_work);
struct radeon_device *rdev = work->rdev;
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id];
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
return -ENOMEM;
struct drm_crtc *crtc = &radeon_crtc->base;
struct drm_framebuffer *fb = work->fb;
work->event = event;
work->rdev = rdev;
work->crtc_id = radeon_crtc->crtc_id;
old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
new_radeon_fb = to_radeon_framebuffer(fb);
/* schedule unpin of the old buffer */
obj = old_radeon_fb->obj;
/* take a reference to the old object */
drm_gem_object_reference(obj);
rbo = gem_to_radeon_bo(obj);
work->old_rbo = rbo;
obj = new_radeon_fb->obj;
rbo = gem_to_radeon_bo(obj);
uint32_t tiling_flags, pitch_pixels;
uint64_t base;
spin_lock(&rbo->tbo.bdev->fence_lock);
if (rbo->tbo.sync_obj)
work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
spin_unlock(&rbo->tbo.bdev->fence_lock);
unsigned long flags;
int r;
INIT_WORK(&work->work, radeon_unpin_work_func);
down_read(&rdev->exclusive_lock);
while (work->fence) {
r = radeon_fence_wait(work->fence, false);
if (r == -EDEADLK) {
up_read(&rdev->exclusive_lock);
r = radeon_gpu_reset(rdev);
down_read(&rdev->exclusive_lock);
}
/* We borrow the event spin lock for protecting unpin_work */
spin_lock_irqsave(&dev->event_lock, flags);
if (radeon_crtc->unpin_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
r = -EBUSY;
goto unlock_free;
if (r) {
DRM_ERROR("failed to wait on page flip fence (%d)!\n",
r);
goto cleanup;
} else
radeon_fence_unref(&work->fence); }
radeon_crtc->unpin_work = work;
radeon_crtc->deferred_flip_completion = 0;
spin_unlock_irqrestore(&dev->event_lock, flags); /* pin the new buffer */ DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
work->old_rbo, rbo);
work->old_rbo, work->new_rbo);
r = radeon_bo_reserve(rbo, false);
r = radeon_bo_reserve(work->new_rbo, false); if (unlikely(r != 0)) { DRM_ERROR("failed to reserve new rbo buffer before flip\n");
goto pflip_cleanup;
goto cleanup; } /* Only 27 bit offset for legacy CRTC */
r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM,
r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM, ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); if (unlikely(r != 0)) {
radeon_bo_unreserve(rbo);
radeon_bo_unreserve(work->new_rbo); r = -EINVAL; DRM_ERROR("failed to pin new rbo buffer before flip\n");
goto pflip_cleanup;
goto cleanup; }
radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
radeon_bo_unreserve(rbo);
radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL);
radeon_bo_unreserve(work->new_rbo); if (!ASIC_IS_AVIVO(rdev)) { /* crtc offset is from display base addr not FB location */
@@ -486,28 +455,91 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, base &= ~7; }
spin_lock_irqsave(&dev->event_lock, flags);
work->new_crtc_base = base;
spin_unlock_irqrestore(&dev->event_lock, flags);
/* update crtc fb */
crtc->primary->fb = fb;
/* We borrow the event spin lock for protecting flip_work */
spin_lock_irqsave(&crtc->dev->event_lock, flags); /* set the proper interrupt */ radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);
return 0;
/* do the flip (mmio) */
radeon_page_flip(rdev, radeon_crtc->crtc_id, base);
-pflip_cleanup:
spin_lock_irqsave(&dev->event_lock, flags);
radeon_crtc->unpin_work = NULL;
-unlock_free:
spin_unlock_irqrestore(&dev->event_lock, flags);
drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
up_read(&rdev->exclusive_lock);
return;
+cleanup:
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); radeon_fence_unref(&work->fence); kfree(work);
up_read(&rdev->exclusive_lock);
+}
+static int radeon_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags)
+{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_framebuffer *old_radeon_fb;
struct radeon_framebuffer *new_radeon_fb;
struct drm_gem_object *obj;
struct radeon_flip_work *work;
unsigned long flags;
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL)
return -ENOMEM;
INIT_WORK(&work->flip_work, radeon_flip_work_func);
INIT_WORK(&work->unpin_work, radeon_unpin_work_func);
return r;
work->rdev = rdev;
work->crtc_id = radeon_crtc->crtc_id;
work->fb = fb;
work->event = event;
/* schedule unpin of the old buffer */
old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
obj = old_radeon_fb->obj;
/* take a reference to the old object */
drm_gem_object_reference(obj);
work->old_rbo = gem_to_radeon_bo(obj);
new_radeon_fb = to_radeon_framebuffer(fb);
obj = new_radeon_fb->obj;
work->new_rbo = gem_to_radeon_bo(obj);
spin_lock(&work->new_rbo->tbo.bdev->fence_lock);
if (work->new_rbo->tbo.sync_obj)
work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj);
spin_unlock(&work->new_rbo->tbo.bdev->fence_lock);
/* update crtc fb */
crtc->primary->fb = fb;
/* We borrow the event spin lock for protecting flip_work */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (radeon_crtc->flip_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
radeon_fence_unref(&work->fence);
kfree(work);
return -EBUSY;
}
radeon_crtc->flip_work = work;
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
queue_work(radeon_crtc->flip_queue, &work->flip_work);
return 0;
}
static int @@ -577,6 +609,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); radeon_crtc->crtc_id = index;
radeon_crtc->flip_queue = create_singlethread_workqueue("radeon-crtc"); rdev->mode_info.crtcs[index] = radeon_crtc; if (rdev->family >= CHIP_BONAIRE) {
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 718be1a..ea72ad8 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -325,8 +325,8 @@ struct radeon_crtc { struct drm_display_mode native_mode; int pll_id; /* page flipping */
struct radeon_unpin_work *unpin_work;
int deferred_flip_completion;
struct workqueue_struct *flip_queue;
struct radeon_flip_work *flip_work; /* pll sharing */ struct radeon_atom_ss ss; bool ss_enabled;
-- 1.9.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
On 27.05.2014 23:49, Christian König wrote:
From: Christian König christian.koenig@amd.com
Instead of trying to flip inside the vblank period when the buffer is idle, offload blocking for idle to a kernel thread and program the flip directly into the hardware.
v2: add error handling, fix EBUSY handling v3: add proper exclusive_lock handling
[...]
- /* update crtc fb */
- crtc->primary->fb = fb;
- /* We borrow the event spin lock for protecting flip_work */
- spin_lock_irqsave(&crtc->dev->event_lock, flags);
- if (radeon_crtc->flip_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
radeon_fence_unref(&work->fence);
kfree(work);
return -EBUSY;
- }
If we return -EBUSY, we shouldn't change crtc->primary->fb, should we? I wonder if crtc->primary->fb shouldn't be changed in radeon_flip_work_func(), when we're sure we can actually flip.
On Wed, May 28, 2014 at 2:56 AM, Michel Dänzer michel@daenzer.net wrote:
On 27.05.2014 23:49, Christian König wrote:
From: Christian König christian.koenig@amd.com
Instead of trying to flip inside the vblank period when the buffer is idle, offload blocking for idle to a kernel thread and program the flip directly into the hardware.
v2: add error handling, fix EBUSY handling v3: add proper exclusive_lock handling
[...]
/* update crtc fb */
crtc->primary->fb = fb;
/* We borrow the event spin lock for protecting flip_work */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (radeon_crtc->flip_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
radeon_fence_unref(&work->fence);
kfree(work);
return -EBUSY;
}
If we return -EBUSY, we shouldn't change crtc->primary->fb, should we? I wonder if crtc->primary->fb shouldn't be changed in radeon_flip_work_func(), when we're sure we can actually flip.
How about this?
Alex
Am 03.06.2014 15:31, schrieb Alex Deucher:
On Wed, May 28, 2014 at 2:56 AM, Michel Dänzer michel@daenzer.net wrote:
On 27.05.2014 23:49, Christian König wrote:
From: Christian König christian.koenig@amd.com
Instead of trying to flip inside the vblank period when the buffer is idle, offload blocking for idle to a kernel thread and program the flip directly into the hardware.
v2: add error handling, fix EBUSY handling v3: add proper exclusive_lock handling
[...]
/* update crtc fb */
crtc->primary->fb = fb;
/* We borrow the event spin lock for protecting flip_work */
spin_lock_irqsave(&crtc->dev->event_lock, flags);
if (radeon_crtc->flip_work) {
DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
radeon_fence_unref(&work->fence);
kfree(work);
return -EBUSY;
}
If we return -EBUSY, we shouldn't change crtc->primary->fb, should we? I wonder if crtc->primary->fb shouldn't be changed in radeon_flip_work_func(), when we're sure we can actually flip.
How about this?
Looks good to me. Reviewed-by: Christian König christian.koenig@amd.com
Alex
On Tue, May 27, 2014 at 10:49 AM, Christian König deathsimple@vodafone.de wrote:
From: Christian König christian.koenig@amd.com
They are doing the same on all generations anyway.
Signed-off-by: Christian König christian.koenig@amd.com
Reviewed-by: Alex Deucher alexander.deucher@amd.com
drivers/gpu/drm/radeon/evergreen.c | 30 ---------------------- drivers/gpu/drm/radeon/r100.c | 30 ---------------------- drivers/gpu/drm/radeon/radeon.h | 4 --- drivers/gpu/drm/radeon/radeon_asic.c | 44 --------------------------------- drivers/gpu/drm/radeon/radeon_asic.h | 6 ----- drivers/gpu/drm/radeon/radeon_display.c | 4 +-- drivers/gpu/drm/radeon/rs600.c | 12 --------- 7 files changed, 2 insertions(+), 128 deletions(-)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index b406546..ec31a82 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1301,36 +1301,6 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) }
/**
- radeon_irq_kms_pflip_irq_get - pre-pageflip callback.
- @rdev: radeon_device pointer
- @crtc: crtc to prepare for pageflip on
- Pre-pageflip callback (evergreen+).
- Enables the pageflip irq (vblank irq).
- */
-void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) -{
/* enable the pflip int */
radeon_irq_kms_pflip_irq_get(rdev, crtc);
-}
-/**
- evergreen_post_page_flip - pos-pageflip callback.
- @rdev: radeon_device pointer
- @crtc: crtc to cleanup pageflip on
- Post-pageflip callback (evergreen+).
- Disables the pageflip irq (vblank irq).
- */
-void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) -{
/* disable the pflip int */
radeon_irq_kms_pflip_irq_put(rdev, crtc);
-}
-/**
- evergreen_page_flip - pageflip callback.
- @rdev: radeon_device pointer
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index b6c3264..840651f 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -142,36 +142,6 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) }
/**
- r100_pre_page_flip - pre-pageflip callback.
- @rdev: radeon_device pointer
- @crtc: crtc to prepare for pageflip on
- Pre-pageflip callback (r1xx-r4xx).
- Enables the pageflip irq (vblank irq).
- */
-void r100_pre_page_flip(struct radeon_device *rdev, int crtc) -{
/* enable the pflip int */
radeon_irq_kms_pflip_irq_get(rdev, crtc);
-}
-/**
- r100_post_page_flip - pos-pageflip callback.
- @rdev: radeon_device pointer
- @crtc: crtc to cleanup pageflip on
- Post-pageflip callback (r1xx-r4xx).
- Disables the pageflip irq (vblank irq).
- */
-void r100_post_page_flip(struct radeon_device *rdev, int crtc) -{
/* disable the pflip int */
radeon_irq_kms_pflip_irq_put(rdev, crtc);
-}
-/**
- r100_page_flip - pageflip callback.
- @rdev: radeon_device pointer
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 325f3a5..2b919af 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1881,9 +1881,7 @@ struct radeon_asic { } dpm; /* pageflipping */ struct {
void (*pre_page_flip)(struct radeon_device *rdev, int crtc); u32 (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
void (*post_page_flip)(struct radeon_device *rdev, int crtc); } pflip;
};
@@ -2742,9 +2740,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_pm_finish(rdev) (rdev)->asic->pm.finish((rdev)) #define radeon_pm_init_profile(rdev) (rdev)->asic->pm.init_profile((rdev)) #define radeon_pm_get_dynpm_state(rdev) (rdev)->asic->pm.get_dynpm_state((rdev)) -#define radeon_pre_page_flip(rdev, crtc) (rdev)->asic->pflip.pre_page_flip((rdev), (crtc)) #define radeon_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base)) -#define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) #define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index ddcd0a2..cb7a0ea 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -248,9 +248,7 @@ static struct radeon_asic r100_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = {
.pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip,
.post_page_flip = &r100_post_page_flip, },
};
@@ -315,9 +313,7 @@ static struct radeon_asic r200_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = {
.pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip,
.post_page_flip = &r100_post_page_flip, },
};
@@ -396,9 +392,7 @@ static struct radeon_asic r300_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = {
.pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip,
.post_page_flip = &r100_post_page_flip, },
};
@@ -463,9 +457,7 @@ static struct radeon_asic r300_asic_pcie = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = {
.pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip,
.post_page_flip = &r100_post_page_flip, },
};
@@ -530,9 +522,7 @@ static struct radeon_asic r420_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = {
.pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip,
.post_page_flip = &r100_post_page_flip, },
};
@@ -597,9 +587,7 @@ static struct radeon_asic rs400_asic = { .set_clock_gating = &radeon_legacy_set_clock_gating, }, .pflip = {
.pre_page_flip = &r100_pre_page_flip, .page_flip = &r100_page_flip,
.post_page_flip = &r100_post_page_flip, },
};
@@ -666,9 +654,7 @@ static struct radeon_asic rs600_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -735,9 +721,7 @@ static struct radeon_asic rs690_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -802,9 +786,7 @@ static struct radeon_asic rv515_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -869,9 +851,7 @@ static struct radeon_asic r520_asic = { .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -968,9 +948,7 @@ static struct radeon_asic r600_asic = { .get_temperature = &rv6xx_get_temp, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -1059,9 +1037,7 @@ static struct radeon_asic rv6xx_asic = { .force_performance_level = &rv6xx_dpm_force_performance_level, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -1150,9 +1126,7 @@ static struct radeon_asic rs780_asic = { .force_performance_level = &rs780_dpm_force_performance_level, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rs600_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -1256,9 +1230,7 @@ static struct radeon_asic rv770_asic = { .vblank_too_short = &rv770_dpm_vblank_too_short, }, .pflip = {
.pre_page_flip = &rs600_pre_page_flip, .page_flip = &rv770_page_flip,
.post_page_flip = &rs600_post_page_flip, },
};
@@ -1375,9 +1347,7 @@ static struct radeon_asic evergreen_asic = { .vblank_too_short = &cypress_dpm_vblank_too_short, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -1467,9 +1437,7 @@ static struct radeon_asic sumo_asic = { .force_performance_level = &sumo_dpm_force_performance_level, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -1560,9 +1528,7 @@ static struct radeon_asic btc_asic = { .vblank_too_short = &btc_dpm_vblank_too_short, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -1704,9 +1670,7 @@ static struct radeon_asic cayman_asic = { .vblank_too_short = &ni_dpm_vblank_too_short, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -1805,9 +1769,7 @@ static struct radeon_asic trinity_asic = { .enable_bapm = &trinity_dpm_enable_bapm, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -1936,9 +1898,7 @@ static struct radeon_asic si_asic = { .vblank_too_short = &ni_dpm_vblank_too_short, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -2099,9 +2059,7 @@ static struct radeon_asic ci_asic = { .powergate_uvd = &ci_dpm_powergate_uvd, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
@@ -2204,9 +2162,7 @@ static struct radeon_asic kv_asic = { .enable_bapm = &kv_dpm_enable_bapm, }, .pflip = {
.pre_page_flip = &evergreen_pre_page_flip, .page_flip = &evergreen_page_flip,
.post_page_flip = &evergreen_post_page_flip, },
};
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e6455b9..953607d 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -135,9 +135,7 @@ extern void r100_pm_prepare(struct radeon_device *rdev); extern void r100_pm_finish(struct radeon_device *rdev); extern void r100_pm_init_profile(struct radeon_device *rdev); extern void r100_pm_get_dynpm_state(struct radeon_device *rdev); -extern void r100_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 r100_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -extern void r100_post_page_flip(struct radeon_device *rdev, int crtc); extern void r100_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int r100_mc_wait_for_idle(struct radeon_device *rdev);
@@ -241,9 +239,7 @@ void rs600_hpd_set_polarity(struct radeon_device *rdev, extern void rs600_pm_misc(struct radeon_device *rdev); extern void rs600_pm_prepare(struct radeon_device *rdev); extern void rs600_pm_finish(struct radeon_device *rdev); -extern void rs600_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 rs600_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -extern void rs600_post_page_flip(struct radeon_device *rdev, int crtc); void rs600_set_safe_registers(struct radeon_device *rdev); extern void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc); extern int rs600_mc_wait_for_idle(struct radeon_device *rdev); @@ -520,9 +516,7 @@ extern void sumo_pm_init_profile(struct radeon_device *rdev); extern void btc_pm_init_profile(struct radeon_device *rdev); int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); -extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc); extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base); -extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc); extern void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc); void evergreen_disable_interrupt_state(struct radeon_device *rdev); int evergreen_mc_wait_for_idle(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 8d99d5e..beccc4a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -342,7 +342,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
drm_vblank_put(rdev->ddev, radeon_crtc->crtc_id); radeon_fence_unref(&work->fence);
radeon_post_page_flip(work->rdev, work->crtc_id);
radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); schedule_work(&work->work);
}
@@ -471,7 +471,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, }
/* set the proper interrupt */
radeon_pre_page_flip(rdev, radeon_crtc->crtc_id);
radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); return 0;
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 72d3616..e005bd7 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -109,18 +109,6 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc) } }
-void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) -{
/* enable the pflip int */
radeon_irq_kms_pflip_irq_get(rdev, crtc);
-}
-void rs600_post_page_flip(struct radeon_device *rdev, int crtc) -{
/* disable the pflip int */
radeon_irq_kms_pflip_irq_put(rdev, crtc);
-}
u32 rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; -- 1.9.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel@lists.freedesktop.org