[PATCH] drm/radeon: Support DRM_MODE_PAGE_FLIP_ASYNC
Christian König
deathsimple at vodafone.de
Fri Apr 1 12:39:15 UTC 2016
Am 01.04.2016 um 11:51 schrieb Michel Dänzer:
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> When this flag is set, we program the hardware to execute the flip
> during horizontal blank (i.e. for the next scanline) instead of during
> vertical blank (i.e. for the next frame).
>
> Currently this is only supported on ASICs which have a page flip
> completion interrupt (>= R600), and only if the use_pflipirq parameter
> has value 2 (the default).
>
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
Reviewed-by: Christian König <christian.koenig at amd.com>
> ---
> drivers/gpu/drm/radeon/atombios_crtc.c | 24 +++++++++++-------------
> drivers/gpu/drm/radeon/evergreen.c | 5 ++++-
> drivers/gpu/drm/radeon/r100.c | 2 +-
> drivers/gpu/drm/radeon/radeon.h | 5 +++--
> drivers/gpu/drm/radeon/radeon_asic.h | 9 +++++----
> drivers/gpu/drm/radeon/radeon_display.c | 6 +++++-
> drivers/gpu/drm/radeon/rs600.c | 4 +++-
> drivers/gpu/drm/radeon/rv770.c | 4 +++-
> 8 files changed, 35 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
> index b80b08f..bdc7b9e 100644
> --- a/drivers/gpu/drm/radeon/atombios_crtc.c
> +++ b/drivers/gpu/drm/radeon/atombios_crtc.c
> @@ -1375,6 +1375,11 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> break;
> }
>
> + /* Make sure surface address is updated at vertical blank rather than
> + * horizontal blank
> + */
> + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +
> WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
> upper_32_bits(fb_location));
> WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
> @@ -1427,12 +1432,6 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
> WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
> (viewport_w << 16) | viewport_h);
>
> - /* pageflip setup */
> - /* make sure flip is at vb rather than hb */
> - tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> - tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> - WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> /* set pageflip to happen only at start of vblank interval (front porch) */
> WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
>
> @@ -1466,7 +1465,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> uint64_t fb_location;
> uint32_t fb_format, fb_pitch_pixels, tiling_flags;
> u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
> - u32 tmp, viewport_w, viewport_h;
> + u32 viewport_w, viewport_h;
> int r;
> bool bypass_lut = false;
>
> @@ -1581,6 +1580,11 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> else
> WREG32(AVIVO_D2VGA_CONTROL, 0);
>
> + /* Make sure surface address is update at vertical blank rather than
> + * horizontal blank
> + */
> + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, 0);
> +
> if (rdev->family >= CHIP_RV770) {
> if (radeon_crtc->crtc_id) {
> WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(fb_location));
> @@ -1627,12 +1631,6 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
> WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
> (viewport_w << 16) | viewport_h);
>
> - /* pageflip setup */
> - /* make sure flip is at vb rather than hb */
> - tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
> - tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
> - WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
> -
> /* set pageflip to happen only at start of vblank interval (front porch) */
> WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
>
> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
> index 76c4bdf..e109239 100644
> --- a/drivers/gpu/drm/radeon/evergreen.c
> +++ b/drivers/gpu/drm/radeon/evergreen.c
> @@ -1407,11 +1407,14 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
> * Triggers the actual pageflip by updating the primary
> * surface base address (evergreen+).
> */
> -void 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,
> + bool async)
> {
> struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
>
> /* update the scanout addresses */
> + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> + async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
> WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
> upper_32_bits(crtc_base));
> WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
> diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
> index 6e478a2..de11a7d 100644
> --- a/drivers/gpu/drm/radeon/r100.c
> +++ b/drivers/gpu/drm/radeon/r100.c
> @@ -153,7 +153,7 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
> * bit to go high, when it does, we release the lock, and allow the
> * double buffered update to take place.
> */
> -void 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, bool async)
> {
> struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
> diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
> index 007be29..f836993 100644
> --- a/drivers/gpu/drm/radeon/radeon.h
> +++ b/drivers/gpu/drm/radeon/radeon.h
> @@ -744,6 +744,7 @@ struct radeon_flip_work {
> struct drm_pending_vblank_event *event;
> struct radeon_bo *old_rbo;
> struct fence *fence;
> + bool async;
> };
>
> struct r500_irq_stat_regs {
> @@ -1998,7 +1999,7 @@ struct radeon_asic {
> } dpm;
> /* pageflipping */
> struct {
> - void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base);
> + void (*page_flip)(struct radeon_device *rdev, int crtc, u64 crtc_base, bool async);
> bool (*page_flip_pending)(struct radeon_device *rdev, int crtc);
> } pflip;
> };
> @@ -2775,7 +2776,7 @@ static inline 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_page_flip(rdev, crtc, base) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base))
> +#define radeon_page_flip(rdev, crtc, base, async) (rdev)->asic->pflip.page_flip((rdev), (crtc), (base), (async))
> #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))
> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h
> index e0aa332..a3deed90 100644
> --- a/drivers/gpu/drm/radeon/radeon_asic.h
> +++ b/drivers/gpu/drm/radeon/radeon_asic.h
> @@ -138,7 +138,7 @@ 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_page_flip(struct radeon_device *rdev, int crtc,
> - u64 crtc_base);
> + u64 crtc_base, bool async);
> 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);
> @@ -250,7 +250,7 @@ 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_page_flip(struct radeon_device *rdev, int crtc,
> - u64 crtc_base);
> + u64 crtc_base, bool async);
> 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);
> @@ -464,7 +464,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);
> -void 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 async);
> 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);
> @@ -534,7 +535,7 @@ 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_page_flip(struct radeon_device *rdev, int crtc,
> - u64 crtc_base);
> + u64 crtc_base, bool async);
> 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);
> diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
> index fcc7483..7f176ec 100644
> --- a/drivers/gpu/drm/radeon/radeon_display.c
> +++ b/drivers/gpu/drm/radeon/radeon_display.c
> @@ -490,7 +490,7 @@ static void radeon_flip_work_func(struct work_struct *__work)
> vblank->linedur_ns / 1000, stat, vpos, hpos);
>
> /* do the flip (mmio) */
> - radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base);
> + radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base, work->async);
>
> radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
> spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
> @@ -525,6 +525,7 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
> work->rdev = rdev;
> work->crtc_id = radeon_crtc->crtc_id;
> work->event = event;
> + work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
>
> /* schedule unpin of the old buffer */
> old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb);
> @@ -1630,6 +1631,9 @@ int radeon_modeset_init(struct radeon_device *rdev)
>
> rdev->ddev->mode_config.funcs = &radeon_mode_funcs;
>
> + if (radeon_use_pflipirq == 2 && rdev->family >= CHIP_R600)
> + rdev->ddev->mode_config.async_page_flip = true;
> +
> if (ASIC_IS_DCE5(rdev)) {
> rdev->ddev->mode_config.max_width = 16384;
> rdev->ddev->mode_config.max_height = 16384;
> diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
> index 6244f4e..90b04d0 100644
> --- a/drivers/gpu/drm/radeon/rs600.c
> +++ b/drivers/gpu/drm/radeon/rs600.c
> @@ -110,7 +110,7 @@ void avivo_wait_for_vblank(struct radeon_device *rdev, int crtc)
> }
> }
>
> -void 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, bool async)
> {
> struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> @@ -121,6 +121,8 @@ void rs600_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
> WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>
> /* update the scanout addresses */
> + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> + async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
> WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
> (u32)crtc_base);
> WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
> diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
> index 01ee96a..2df7901 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;
> }
>
> -void 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, bool async)
> {
> struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
> u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
> @@ -812,6 +812,8 @@ void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
> WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
>
> /* update the scanout addresses */
> + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
> + async ? AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
> if (radeon_crtc->crtc_id) {
> WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
> WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
More information about the dri-devel
mailing list