[Intel-gfx] [PATCH 3/5] drm: Allow the driver to reject vblank requests only when it really has the vblank interrupts disabled (original) (raw)

Jesse Barnes jbarnes at virtuousgeek.org
Wed Feb 26 11:41:58 PST 2014


On Fri, 21 Feb 2014 21:03:33 +0200 ville.syrjala at linux.intel.com wrote:

From: Ville Syrjälä <ville.syrjala at linux.intel.com>

Allow the driver to specify whether all new vblank requests after drmvblankoff() should be rejected. And add a counterpart called drmvblankon() which will again allow vblank requests to come in. Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com> --- drivers/gpu/drm/armada/armadacrtc.c | 2 +- drivers/gpu/drm/drmirq.c | 29 ++++++++++++++++++++++++++++- drivers/gpu/drm/exynos/exynosdrmcrtc.c | 2 +- drivers/gpu/drm/gma500/gmadisplay.c | 2 +- drivers/gpu/drm/i915/inteldisplay.c | 6 +++--- drivers/gpu/drm/tegra/dc.c | 2 +- include/drm/drmP.h | 4 +++- 7 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/armada/armadacrtc.c b/drivers/gpu/drm/armada/armadacrtc.c index d8e3982..74317b2 100644 --- a/drivers/gpu/drm/armada/armadacrtc.c +++ b/drivers/gpu/drm/armada/armadacrtc.c @@ -257,7 +257,7 @@ static void armadadrmvblankoff(struct armadacrtc *dcrtc) * Tell the DRM core that vblank IRQs aren't going to happen for * a while. This cleans up any pending vblank events for us. */ - drmvblankoff(dev, dcrtc->num); + drmvblankoff(dev, dcrtc->num, false); /* Handle any pending flip event. */ spinlockirq(&dev->eventlock); diff --git a/drivers/gpu/drm/drmirq.c b/drivers/gpu/drm/drmirq.c index 3211158..6e5d820 100644 --- a/drivers/gpu/drm/drmirq.c +++ b/drivers/gpu/drm/drmirq.c @@ -890,6 +890,12 @@ int drmvblankget(struct drmdevice *dev, int crtc) int ret = 0; spinlockirqsave(&dev->vbllock, irqflags); + + if (dev->vblank[crtc].reject) { + ret = -EINVAL; + goto out; + } + /* Going from 0->1 means we have to enable interrupts again */ if (atomicaddreturn(1, &dev->vblank[crtc].refcount) == 1) { spinlock(&dev->vblanktimelock); @@ -917,6 +923,8 @@ int drmvblankget(struct drmdevice *dev, int crtc) ret = -EINVAL; } } + + out: spinunlockirqrestore(&dev->vbllock, irqflags); return ret; @@ -947,8 +955,9 @@ EXPORTSYMBOL(drmvblankput); * drmvblankoff - disable vblank events on a CRTC * @dev: DRM device * @crtc: CRTC in question + * @reject: reject drmvblankget() until drmvblankon() has been called? */ -void drmvblankoff(struct drmdevice *dev, int crtc) +void drmvblankoff(struct drmdevice *dev, int crtc, bool reject) { struct drmpendingvblankevent *e, *t; struct timeval now; @@ -956,6 +965,7 @@ void drmvblankoff(struct drmdevice *dev, int crtc) unsigned int seq; spinlockirqsave(&dev->vbllock, irqflags); + dev->vblank[crtc].reject = reject; vblankdisableandsave(dev, crtc); wakeup(&dev->vblank[crtc].queue); @@ -979,6 +989,22 @@ void drmvblankoff(struct drmdevice *dev, int crtc) } EXPORTSYMBOL(drmvblankoff); + +/** + * drmvblankon - enable vblank events on a CRTC + * @dev: DRM device + * @crtc: CRTC in question + */ +void drmvblankon(struct drmdevice *dev, int crtc) +{ + unsigned long irqflags; + + spinlockirqsave(&dev->vbllock, irqflags); + dev->vblank[crtc].reject = false; + spinunlockirqrestore(&dev->vbllock, irqflags); +} +EXPORTSYMBOL(drmvblankon); + /** * drmvblankpremodeset - account for vblanks across mode sets * @dev: DRM device @@ -1224,6 +1250,7 @@ int drmwaitvblank(struct drmdevice *dev, void *data, DRMWAITON(ret, dev->vblank[crtc].queue, 3 * HZ, (((drmvblankcount(dev, crtc) - vblwait->request.sequence) <= (1 << 23)) ||_ _+ dev->vblank[crtc].reject || !dev->irqenabled)); if (ret != -EINTR) { diff --git a/drivers/gpu/drm/exynos/exynosdrmcrtc.c b/drivers/gpu/drm/exynos/exynosdrmcrtc.c index ebc0150..e2d6b9d 100644 --- a/drivers/gpu/drm/exynos/exynosdrmcrtc.c +++ b/drivers/gpu/drm/exynos/exynosdrmcrtc.c @@ -68,7 +68,7 @@ static void exynosdrmcrtcdpms(struct drmcrtc *crtc, int mode) /* wait for the completion of page flip. */ waitevent(exynoscrtc->pendingflipqueue, atomicread(&exynoscrtc->pendingflip) == 0); - drmvblankoff(crtc->dev, exynoscrtc->pipe); + drmvblankoff(crtc->dev, exynoscrtc->pipe, false); } exynosdrmfnencoder(crtc, &mode, exynosdrmencodercrtcdpms); diff --git a/drivers/gpu/drm/gma500/gmadisplay.c b/drivers/gpu/drm/gma500/gmadisplay.c index 386de2c..ff18220 100644 --- a/drivers/gpu/drm/gma500/gmadisplay.c +++ b/drivers/gpu/drm/gma500/gmadisplay.c @@ -281,7 +281,7 @@ void gmacrtcdpms(struct drmcrtc *crtc, int mode) REGWRITE(VGACNTRL, VGADISPDISABLE); /* Turn off vblank interrupts */ - drmvblankoff(dev, pipe); + drmvblankoff(dev, pipe, false); /* Wait for vblank for the disable to take effect */ gmawaitforvblank(dev); diff --git a/drivers/gpu/drm/i915/inteldisplay.c b/drivers/gpu/drm/i915/inteldisplay.c index f19e6ea..bab0d08 100644 --- a/drivers/gpu/drm/i915/inteldisplay.c +++ b/drivers/gpu/drm/i915/inteldisplay.c @@ -3643,7 +3643,7 @@ static void haswellcrtcdisableplanes(struct drmcrtc *crtc) int plane = intelcrtc->plane; intelcrtcwaitforpendingflips(crtc); - drmvblankoff(dev, pipe); + drmvblankoff(dev, pipe, false); /* FBC must be disabled before disabling the plane on HSW. */ if (devpriv->fbc.plane == plane) @@ -3774,7 +3774,7 @@ static void ironlakecrtcdisable(struct drmcrtc *crtc) encoder->disable(encoder); intelcrtcwaitforpendingflips(crtc); - drmvblankoff(dev, pipe); + drmvblankoff(dev, pipe, false); if (devpriv->fbc.plane == plane) inteldisablefbc(dev); @@ -4239,7 +4239,7 @@ static void i9xxcrtcdisable(struct drmcrtc *crtc) /* Give the overlay scaler a chance to disable if it's on this pipe */ intelcrtcwaitforpendingflips(crtc); - drmvblankoff(dev, pipe); + drmvblankoff(dev, pipe, false); if (devpriv->fbc.plane == plane) inteldisablefbc(dev); diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 9336006..480bfec 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -324,7 +324,7 @@ static void tegracrtcdisable(struct drmcrtc *crtc) } } - drmvblankoff(drm, dc->pipe); + drmvblankoff(drm, dc->pipe, false); } static bool tegracrtcmodefixup(struct drmcrtc *crtc, diff --git a/include/drm/drmP.h b/include/drm/drmP.h index f974da9..ee40483 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1090,6 +1090,7 @@ struct drmvblankcrtc { int crtc; /* crtc index */ bool enabled; /* so we don't call enable more than once per disable */ + bool reject; /* reject drmvblankget()? */ }; /** @@ -1400,7 +1401,8 @@ extern void drmsendvblankevent(struct drmdevice *dev, int crtc, extern bool drmhandlevblank(struct drmdevice *dev, int crtc); extern int drmvblankget(struct drmdevice *dev, int crtc); extern void drmvblankput(struct drmdevice *dev, int crtc); -extern void drmvblankoff(struct drmdevice *dev, int crtc); +extern void drmvblankoff(struct drmdevice *dev, int crtc, bool reject); +extern void drmvblankon(struct drmdevice *dev, int crtc); extern void drmvblankcleanup(struct drmdevice *dev); extern u32 drmgetlastvbltimestamp(struct drmdevice *dev, int crtc, struct timeval *tvblank, unsigned flags);

Reviewed-by: Jesse Barnes <jbarnes at virtuousgeek.org>

-- Jesse Barnes, Intel Open Source Technology Center



More information about the dri-devel mailing list