[PATCH] drm/radeon: Support DRM_MODE_PAGE_FLIP_ASYNC
Alex Deucher
alexdeucher at gmail.com
Fri Apr 1 15:08:32 UTC 2016
On Fri, Apr 1, 2016 at 8:39 AM, Christian König <deathsimple at vodafone.de> wrote:
> 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>
>
Applied. thanks!
Alex
>
>> ---
>> 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));
>
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
More information about the dri-devel
mailing list