[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