drm/i915/gvt: Enable async flip on plane surface mmio writes
authorColin Xu <colin.xu@intel.com>
Mon, 25 Mar 2019 01:52:17 +0000 (09:52 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Fri, 29 Mar 2019 03:10:22 +0000 (11:10 +0800)
According to Intel GFX PRM on 01.org, plane surface address can be updated
synchronously or asynchronously. Synchronous flip will hold plane surface
address update to start of next vsync, which is current implementation.
Asynchronous flip will update the address as soon as possible. Without
async flip, some 3D application could not reach better performance and
the maximum performance is no higher than vsync frequency.

The patch enables the async flip on plane surface address mmio update,
and increment flip count correctly.

With async flip enabled, some 3D applications have significant performance
improvement. i.e. 3DMark Ice Storm has a 300%~400% increment on score.

v2:
Use bit operation definition for flip mode. (zhenyu)

Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Colin Xu <colin.xu@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/display.c
drivers/gpu/drm/i915/gvt/handlers.c

index 035479e273beca866575c4bef70438583029d2df..d7536e41aff95cf656321c669114cc9f31a0a4ed 100644 (file)
@@ -407,7 +407,6 @@ static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
                if (!pipe_is_enabled(vgpu, pipe))
                        continue;
 
-               vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++;
                intel_vgpu_trigger_virtual_event(vgpu, event);
        }
 
index de7fb67b5fa77d032abfde0d512cfee57a77c1cc..1a343f99b3b4109e9062e11e29a751af2c52219c 100644 (file)
@@ -750,18 +750,19 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                void *p_data, unsigned int bytes)
 {
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
-       unsigned int index = DSPSURF_TO_PIPE(offset);
-       i915_reg_t surflive_reg = DSPSURFLIVE(index);
-       int flip_event[] = {
-               [PIPE_A] = PRIMARY_A_FLIP_DONE,
-               [PIPE_B] = PRIMARY_B_FLIP_DONE,
-               [PIPE_C] = PRIMARY_C_FLIP_DONE,
-       };
+       u32 pipe = DSPSURF_TO_PIPE(offset);
+       int event = SKL_FLIP_EVENT(pipe, PLANE_PRIMARY);
 
        write_vreg(vgpu, offset, p_data, bytes);
-       vgpu_vreg_t(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
+       vgpu_vreg_t(vgpu, DSPSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset);
+
+       vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++;
+
+       if (vgpu_vreg_t(vgpu, DSPCNTR(pipe)) & PLANE_CTL_ASYNC_FLIP)
+               intel_vgpu_trigger_virtual_event(vgpu, event);
+       else
+               set_bit(event, vgpu->irq.flip_done_event[pipe]);
 
-       set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
        return 0;
 }
 
@@ -771,18 +772,42 @@ static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
 static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                void *p_data, unsigned int bytes)
 {
-       unsigned int index = SPRSURF_TO_PIPE(offset);
-       i915_reg_t surflive_reg = SPRSURFLIVE(index);
-       int flip_event[] = {
-               [PIPE_A] = SPRITE_A_FLIP_DONE,
-               [PIPE_B] = SPRITE_B_FLIP_DONE,
-               [PIPE_C] = SPRITE_C_FLIP_DONE,
-       };
+       u32 pipe = SPRSURF_TO_PIPE(offset);
+       int event = SKL_FLIP_EVENT(pipe, PLANE_SPRITE0);
 
        write_vreg(vgpu, offset, p_data, bytes);
-       vgpu_vreg_t(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset);
+       vgpu_vreg_t(vgpu, SPRSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset);
+
+       if (vgpu_vreg_t(vgpu, SPRCTL(pipe)) & PLANE_CTL_ASYNC_FLIP)
+               intel_vgpu_trigger_virtual_event(vgpu, event);
+       else
+               set_bit(event, vgpu->irq.flip_done_event[pipe]);
+
+       return 0;
+}
+
+static int reg50080_mmio_write(struct intel_vgpu *vgpu,
+                              unsigned int offset, void *p_data,
+                              unsigned int bytes)
+{
+       struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+       enum pipe pipe = REG_50080_TO_PIPE(offset);
+       enum plane_id plane = REG_50080_TO_PLANE(offset);
+       int event = SKL_FLIP_EVENT(pipe, plane);
+
+       write_vreg(vgpu, offset, p_data, bytes);
+       if (plane == PLANE_PRIMARY) {
+               vgpu_vreg_t(vgpu, DSPSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset);
+               vgpu_vreg_t(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++;
+       } else {
+               vgpu_vreg_t(vgpu, SPRSURFLIVE(pipe)) = vgpu_vreg(vgpu, offset);
+       }
+
+       if ((vgpu_vreg(vgpu, offset) & REG50080_FLIP_TYPE_MASK) == REG50080_FLIP_TYPE_ASYNC)
+               intel_vgpu_trigger_virtual_event(vgpu, event);
+       else
+               set_bit(event, vgpu->irq.flip_done_event[pipe]);
 
-       set_bit(flip_event[index], vgpu->irq.flip_done_event[index]);
        return 0;
 }
 
@@ -1969,6 +1994,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_DH(DSPSURF(PIPE_A), D_ALL, NULL, pri_surf_mmio_write);
        MMIO_D(DSPOFFSET(PIPE_A), D_ALL);
        MMIO_D(DSPSURFLIVE(PIPE_A), D_ALL);
+       MMIO_DH(REG_50080(PIPE_A, PLANE_PRIMARY), D_ALL, NULL,
+               reg50080_mmio_write);
 
        MMIO_D(DSPCNTR(PIPE_B), D_ALL);
        MMIO_D(DSPADDR(PIPE_B), D_ALL);
@@ -1978,6 +2005,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_DH(DSPSURF(PIPE_B), D_ALL, NULL, pri_surf_mmio_write);
        MMIO_D(DSPOFFSET(PIPE_B), D_ALL);
        MMIO_D(DSPSURFLIVE(PIPE_B), D_ALL);
+       MMIO_DH(REG_50080(PIPE_B, PLANE_PRIMARY), D_ALL, NULL,
+               reg50080_mmio_write);
 
        MMIO_D(DSPCNTR(PIPE_C), D_ALL);
        MMIO_D(DSPADDR(PIPE_C), D_ALL);
@@ -1987,6 +2016,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_DH(DSPSURF(PIPE_C), D_ALL, NULL, pri_surf_mmio_write);
        MMIO_D(DSPOFFSET(PIPE_C), D_ALL);
        MMIO_D(DSPSURFLIVE(PIPE_C), D_ALL);
+       MMIO_DH(REG_50080(PIPE_C, PLANE_PRIMARY), D_ALL, NULL,
+               reg50080_mmio_write);
 
        MMIO_D(SPRCTL(PIPE_A), D_ALL);
        MMIO_D(SPRLINOFF(PIPE_A), D_ALL);
@@ -2000,6 +2031,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_D(SPROFFSET(PIPE_A), D_ALL);
        MMIO_D(SPRSCALE(PIPE_A), D_ALL);
        MMIO_D(SPRSURFLIVE(PIPE_A), D_ALL);
+       MMIO_DH(REG_50080(PIPE_A, PLANE_SPRITE0), D_ALL, NULL,
+               reg50080_mmio_write);
 
        MMIO_D(SPRCTL(PIPE_B), D_ALL);
        MMIO_D(SPRLINOFF(PIPE_B), D_ALL);
@@ -2013,6 +2046,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_D(SPROFFSET(PIPE_B), D_ALL);
        MMIO_D(SPRSCALE(PIPE_B), D_ALL);
        MMIO_D(SPRSURFLIVE(PIPE_B), D_ALL);
+       MMIO_DH(REG_50080(PIPE_B, PLANE_SPRITE0), D_ALL, NULL,
+               reg50080_mmio_write);
 
        MMIO_D(SPRCTL(PIPE_C), D_ALL);
        MMIO_D(SPRLINOFF(PIPE_C), D_ALL);
@@ -2026,6 +2061,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_D(SPROFFSET(PIPE_C), D_ALL);
        MMIO_D(SPRSCALE(PIPE_C), D_ALL);
        MMIO_D(SPRSURFLIVE(PIPE_C), D_ALL);
+       MMIO_DH(REG_50080(PIPE_C, PLANE_SPRITE0), D_ALL, NULL,
+               reg50080_mmio_write);
 
        MMIO_D(HTOTAL(TRANSCODER_A), D_ALL);
        MMIO_D(HBLANK(TRANSCODER_A), D_ALL);