diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-02-13 15:03:42 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-02-23 04:53:38 -0500 |
commit | 9625604cebcb3f5be2e692408274734e8ae63979 (patch) | |
tree | 50cd339be396fcedf52d3a71827f8f24a0b95756 | |
parent | d4495cbaa5869d2ce8f4b1c9331d3a19b24eb98b (diff) |
drm/irq: Add drm_crtc_vblank_reset
At driver load we need to tell the vblank code about the state of the
pipes, so that the logic around reject vblank_get when the pipe is off
works correctly.
Thus far i915 used drm_vblank_off, but one of the side-effects of it
is that it also saves the vblank counter. And for that it calls down
into the ->get_vblank_counter hook. Which isn't really a good idea
when the pipe is off for a few reasons:
- With runtime pm the register might not respond.
- If the pipe is off some datastructures might not be around or
unitialized.
The later is what blew up on gen3: We look at intel_crtc->config to
compute the vblank counter, and for a disabled pipe at boot-up that's
just not there. Thus far this was papered over by a check for
intel_crtc->active, but I want to get rid of that (since it's fairly
race, vblank hooks are called from all kinds of places).
So prep for that by adding a _reset functions which only does what we
really need to be done at driver load: Mark the vblank pipe as off,
but don't do any vblank counter saving or event flushing - neither of
that is required.
v2: Clarify the code flow slightly as suggested by Ville.
v3: Fix kerneldoc spelling, spotted by Laurent.
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Imre Deak <imre.deak@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com> (v2)
Acked-by: Dave Airlie <airlied@redhat.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 6 | ||||
-rw-r--r-- | include/drm/drmP.h | 1 |
3 files changed, 36 insertions, 3 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 75647e7f012b..e78a1f5cad9c 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -1226,6 +1226,38 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc) | |||
1226 | EXPORT_SYMBOL(drm_crtc_vblank_off); | 1226 | EXPORT_SYMBOL(drm_crtc_vblank_off); |
1227 | 1227 | ||
1228 | /** | 1228 | /** |
1229 | * drm_crtc_vblank_reset - reset vblank state to off on a CRTC | ||
1230 | * @crtc: CRTC in question | ||
1231 | * | ||
1232 | * Drivers can use this function to reset the vblank state to off at load time. | ||
1233 | * Drivers should use this together with the drm_crtc_vblank_off() and | ||
1234 | * drm_crtc_vblank_on() functions. The difference compared to | ||
1235 | * drm_crtc_vblank_off() is that this function doesn't save the vblank counter | ||
1236 | * and hence doesn't need to call any driver hooks. | ||
1237 | */ | ||
1238 | void drm_crtc_vblank_reset(struct drm_crtc *drm_crtc) | ||
1239 | { | ||
1240 | struct drm_device *dev = drm_crtc->dev; | ||
1241 | unsigned long irqflags; | ||
1242 | int crtc = drm_crtc_index(drm_crtc); | ||
1243 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; | ||
1244 | |||
1245 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | ||
1246 | /* | ||
1247 | * Prevent subsequent drm_vblank_get() from enabling the vblank | ||
1248 | * interrupt by bumping the refcount. | ||
1249 | */ | ||
1250 | if (!vblank->inmodeset) { | ||
1251 | atomic_inc(&vblank->refcount); | ||
1252 | vblank->inmodeset = 1; | ||
1253 | } | ||
1254 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | ||
1255 | |||
1256 | WARN_ON(!list_empty(&dev->vblank_event_list)); | ||
1257 | } | ||
1258 | EXPORT_SYMBOL(drm_crtc_vblank_reset); | ||
1259 | |||
1260 | /** | ||
1229 | * drm_vblank_on - enable vblank events on a CRTC | 1261 | * drm_vblank_on - enable vblank events on a CRTC |
1230 | * @dev: DRM device | 1262 | * @dev: DRM device |
1231 | * @crtc: CRTC in question | 1263 | * @crtc: CRTC in question |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3b0fe9f1f3c9..b901b00a8f2e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -13316,11 +13316,11 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) | |||
13316 | I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); | 13316 | I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); |
13317 | 13317 | ||
13318 | /* restore vblank interrupts to correct state */ | 13318 | /* restore vblank interrupts to correct state */ |
13319 | drm_crtc_vblank_reset(&crtc->base); | ||
13319 | if (crtc->active) { | 13320 | if (crtc->active) { |
13320 | update_scanline_offset(crtc); | 13321 | update_scanline_offset(crtc); |
13321 | drm_vblank_on(dev, crtc->pipe); | 13322 | drm_crtc_vblank_on(&crtc->base); |
13322 | } else | 13323 | } |
13323 | drm_vblank_off(dev, crtc->pipe); | ||
13324 | 13324 | ||
13325 | /* We need to sanitize the plane -> pipe mapping first because this will | 13325 | /* We need to sanitize the plane -> pipe mapping first because this will |
13326 | * disable the crtc (and hence change the state) if it is wrong. Note | 13326 | * disable the crtc (and hence change the state) if it is wrong. Note |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index e928625a9da0..54c6ea1e5866 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -922,6 +922,7 @@ extern void drm_crtc_wait_one_vblank(struct drm_crtc *crtc); | |||
922 | extern void drm_vblank_off(struct drm_device *dev, int crtc); | 922 | extern void drm_vblank_off(struct drm_device *dev, int crtc); |
923 | extern void drm_vblank_on(struct drm_device *dev, int crtc); | 923 | extern void drm_vblank_on(struct drm_device *dev, int crtc); |
924 | extern void drm_crtc_vblank_off(struct drm_crtc *crtc); | 924 | extern void drm_crtc_vblank_off(struct drm_crtc *crtc); |
925 | extern void drm_crtc_vblank_reset(struct drm_crtc *crtc); | ||
925 | extern void drm_crtc_vblank_on(struct drm_crtc *crtc); | 926 | extern void drm_crtc_vblank_on(struct drm_crtc *crtc); |
926 | extern void drm_vblank_cleanup(struct drm_device *dev); | 927 | extern void drm_vblank_cleanup(struct drm_device *dev); |
927 | 928 | ||