aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2015-02-13 15:03:42 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-02-23 04:53:38 -0500
commit9625604cebcb3f5be2e692408274734e8ae63979 (patch)
tree50cd339be396fcedf52d3a71827f8f24a0b95756
parentd4495cbaa5869d2ce8f4b1c9331d3a19b24eb98b (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.c32
-rw-r--r--drivers/gpu/drm/i915/intel_display.c6
-rw-r--r--include/drm/drmP.h1
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)
1226EXPORT_SYMBOL(drm_crtc_vblank_off); 1226EXPORT_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 */
1238void 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}
1258EXPORT_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);
922extern void drm_vblank_off(struct drm_device *dev, int crtc); 922extern void drm_vblank_off(struct drm_device *dev, int crtc);
923extern void drm_vblank_on(struct drm_device *dev, int crtc); 923extern void drm_vblank_on(struct drm_device *dev, int crtc);
924extern void drm_crtc_vblank_off(struct drm_crtc *crtc); 924extern void drm_crtc_vblank_off(struct drm_crtc *crtc);
925extern void drm_crtc_vblank_reset(struct drm_crtc *crtc);
925extern void drm_crtc_vblank_on(struct drm_crtc *crtc); 926extern void drm_crtc_vblank_on(struct drm_crtc *crtc);
926extern void drm_vblank_cleanup(struct drm_device *dev); 927extern void drm_vblank_cleanup(struct drm_device *dev);
927 928