[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