i915_irq.c 14.5 KB
Newer Older
Dave Airlie's avatar
Dave Airlie committed
1
/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
Linus Torvalds's avatar
Linus Torvalds committed
2
 */
Dave Airlie's avatar
Dave Airlie committed
3
/*
Linus Torvalds's avatar
Linus Torvalds committed
4 5
 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
 * All Rights Reserved.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
Dave Airlie's avatar
Dave Airlie committed
27
 */
Linus Torvalds's avatar
Linus Torvalds committed
28 29 30 31 32 33 34 35

#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"

#define MAX_NOPID ((u32)~0)

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
/**
 * Interrupts that are always left unmasked.
 *
 * Since pipe events are edge-triggered from the PIPESTAT register to IIR,
 * we leave them always unmasked in IMR and then control enabling them through
 * PIPESTAT alone.
 */
#define I915_INTERRUPT_ENABLE_FIX (I915_ASLE_INTERRUPT | \
				   I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |  \
				   I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)

/** Interrupts that we mask and unmask at runtime. */
#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)

/** These are all of the interrupts used by the driver */
#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
				    I915_INTERRUPT_ENABLE_VAR)
53

54
void
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
	if ((dev_priv->irq_mask_reg & mask) != 0) {
		dev_priv->irq_mask_reg &= ~mask;
		I915_WRITE(IMR, dev_priv->irq_mask_reg);
		(void) I915_READ(IMR);
	}
}

static inline void
i915_disable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
	if ((dev_priv->irq_mask_reg & mask) != mask) {
		dev_priv->irq_mask_reg |= mask;
		I915_WRITE(IMR, dev_priv->irq_mask_reg);
		(void) I915_READ(IMR);
	}
}

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
static inline u32
i915_pipestat(int pipe)
{
	if (pipe == 0)
		return PIPEASTAT;
	if (pipe == 1)
		return PIPEBSTAT;
	BUG_ON(1);
}

void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
{
	if ((dev_priv->pipestat[pipe] & mask) != mask) {
		u32 reg = i915_pipestat(pipe);

		dev_priv->pipestat[pipe] |= mask;
		/* Enable the interrupt, clear any pending status */
		I915_WRITE(reg, dev_priv->pipestat[pipe] | (mask >> 16));
		(void) I915_READ(reg);
	}
}

void
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
{
	if ((dev_priv->pipestat[pipe] & mask) != 0) {
		u32 reg = i915_pipestat(pipe);

		dev_priv->pipestat[pipe] &= ~mask;
		I915_WRITE(reg, dev_priv->pipestat[pipe]);
		(void) I915_READ(reg);
	}
}

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
/**
 * i915_pipe_enabled - check if a pipe is enabled
 * @dev: DRM device
 * @pipe: pipe to check
 *
 * Reading certain registers when the pipe is disabled can hang the chip.
 * Use this routine to make sure the PLL is running and the pipe is active
 * before reading such registers if unsure.
 */
static int
i915_pipe_enabled(struct drm_device *dev, int pipe)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;

	if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
		return 1;

	return 0;
}

130 131 132 133
/* Called from drm generic code, passed a 'crtc', which
 * we use as a pipe index
 */
u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	unsigned long high_frame;
	unsigned long low_frame;
	u32 high1, high2, low, count;

	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;

	if (!i915_pipe_enabled(dev, pipe)) {
		DRM_ERROR("trying to get vblank count for disabled pipe %d\n", pipe);
		return 0;
	}

	/*
	 * High & low register fields aren't synchronized, so make sure
	 * we get a low value that's stable across two reads of the high
	 * register.
	 */
	do {
		high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
			 PIPE_FRAME_HIGH_SHIFT);
		low =  ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
			PIPE_FRAME_LOW_SHIFT);
		high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
			 PIPE_FRAME_HIGH_SHIFT);
	} while (high1 != high2);

	count = (high1 << 8) | low;

	return count;
}

Linus Torvalds's avatar
Linus Torvalds committed
167 168
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
169
	struct drm_device *dev = (struct drm_device *) arg;
Linus Torvalds's avatar
Linus Torvalds committed
170
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
171 172
	u32 iir, new_iir;
	u32 pipea_stats, pipeb_stats;
173
	int vblank = 0;
174
	unsigned long irqflags;
175

176 177
	atomic_inc(&dev_priv->irq_received);

178
	iir = I915_READ(IIR);
179

180
	if (iir == 0)
181 182
		return IRQ_NONE;

183 184 185 186 187 188 189 190 191 192 193 194 195
	do {
		pipea_stats = 0;
		pipeb_stats = 0;
		/*
		 * Clear the PIPE(A|B)STAT regs before the IIR
		 */
		if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
			spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
			pipea_stats = I915_READ(PIPEASTAT);
			I915_WRITE(PIPEASTAT, pipea_stats);
			spin_unlock_irqrestore(&dev_priv->user_irq_lock,
					       irqflags);
		}
Linus Torvalds's avatar
Linus Torvalds committed
196

197 198 199 200 201 202 203
		if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
			spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
			pipeb_stats = I915_READ(PIPEBSTAT);
			I915_WRITE(PIPEBSTAT, pipeb_stats);
			spin_unlock_irqrestore(&dev_priv->user_irq_lock,
					       irqflags);
		}
204

205 206
		I915_WRITE(IIR, iir);
		new_iir = I915_READ(IIR); /* Flush posted writes */
207

208 209 210
		if (dev_priv->sarea_priv)
			dev_priv->sarea_priv->last_dispatch =
				READ_BREADCRUMB(dev_priv);
211

212 213 214 215
		if (iir & I915_USER_INTERRUPT) {
			dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
			DRM_WAKEUP(&dev_priv->irq_queue);
		}
216

217 218 219 220
		if (pipea_stats & I915_VBLANK_INTERRUPT_STATUS) {
			vblank++;
			drm_handle_vblank(dev, 0);
		}
221

222 223 224 225
		if (pipeb_stats & I915_VBLANK_INTERRUPT_STATUS) {
			vblank++;
			drm_handle_vblank(dev, 1);
		}
226

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
		if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
		    (iir & I915_ASLE_INTERRUPT))
			opregion_asle_intr(dev);

		/* With MSI, interrupts are only generated when iir
		 * transitions from zero to nonzero.  If another bit got
		 * set while we were handling the existing iir bits, then
		 * we would never get another interrupt.
		 *
		 * This is fine on non-MSI as well, as if we hit this path
		 * we avoid exiting the interrupt handler only to generate
		 * another one.
		 *
		 * Note that for MSI this could cause a stray interrupt report
		 * if an interrupt landed in the time between writing IIR and
		 * the posting read.  This should be rare enough to never
		 * trigger the 99% of 100,000 interrupts test for disabling
		 * stray interrupts.
		 */
		iir = new_iir;
	} while (iir != 0);
248

Linus Torvalds's avatar
Linus Torvalds committed
249 250 251
	return IRQ_HANDLED;
}

252
static int i915_emit_irq(struct drm_device * dev)
Linus Torvalds's avatar
Linus Torvalds committed
253 254 255 256 257 258
{
	drm_i915_private_t *dev_priv = dev->dev_private;
	RING_LOCALS;

	i915_kernel_lost_context(dev);

259
	DRM_DEBUG("\n");
Linus Torvalds's avatar
Linus Torvalds committed
260

261
	dev_priv->counter++;
262
	if (dev_priv->counter > 0x7FFFFFFFUL)
263 264 265
		dev_priv->counter = 1;
	if (dev_priv->sarea_priv)
		dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
266

267
	BEGIN_LP_RING(4);
268
	OUT_RING(MI_STORE_DWORD_INDEX);
269
	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
270
	OUT_RING(dev_priv->counter);
271
	OUT_RING(MI_USER_INTERRUPT);
Linus Torvalds's avatar
Linus Torvalds committed
272
	ADVANCE_LP_RING();
273

274
	return dev_priv->counter;
Linus Torvalds's avatar
Linus Torvalds committed
275 276
}

277
void i915_user_irq_get(struct drm_device *dev)
278 279
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
280
	unsigned long irqflags;
281

282
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
283 284
	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
285
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
286 287
}

288
void i915_user_irq_put(struct drm_device *dev)
289 290
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
291
	unsigned long irqflags;
292

293
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
294 295 296
	BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
	if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
		i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
297
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
298 299
}

300
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
Linus Torvalds's avatar
Linus Torvalds committed
301 302 303 304
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	int ret = 0;

305
	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
Linus Torvalds's avatar
Linus Torvalds committed
306 307
		  READ_BREADCRUMB(dev_priv));

308
	if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
309 310 311 312
		if (dev_priv->sarea_priv) {
			dev_priv->sarea_priv->last_dispatch =
				READ_BREADCRUMB(dev_priv);
		}
Linus Torvalds's avatar
Linus Torvalds committed
313
		return 0;
314
	}
Linus Torvalds's avatar
Linus Torvalds committed
315

316 317
	if (dev_priv->sarea_priv)
		dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
Linus Torvalds's avatar
Linus Torvalds committed
318

319
	i915_user_irq_get(dev);
Linus Torvalds's avatar
Linus Torvalds committed
320 321
	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
		    READ_BREADCRUMB(dev_priv) >= irq_nr);
322
	i915_user_irq_put(dev);
Linus Torvalds's avatar
Linus Torvalds committed
323

Eric Anholt's avatar
Eric Anholt committed
324
	if (ret == -EBUSY) {
325
		DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
Linus Torvalds's avatar
Linus Torvalds committed
326 327 328
			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
	}

329 330 331
	if (dev_priv->sarea_priv)
		dev_priv->sarea_priv->last_dispatch =
			READ_BREADCRUMB(dev_priv);
332 333 334 335

	return ret;
}

Linus Torvalds's avatar
Linus Torvalds committed
336 337
/* Needs the lock as it touches the ring.
 */
338 339
int i915_irq_emit(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
Linus Torvalds's avatar
Linus Torvalds committed
340 341
{
	drm_i915_private_t *dev_priv = dev->dev_private;
342
	drm_i915_irq_emit_t *emit = data;
Linus Torvalds's avatar
Linus Torvalds committed
343 344
	int result;

345
	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
Linus Torvalds's avatar
Linus Torvalds committed
346 347

	if (!dev_priv) {
348
		DRM_ERROR("called with no initialization\n");
Eric Anholt's avatar
Eric Anholt committed
349
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
350
	}
351
	mutex_lock(&dev->struct_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
352
	result = i915_emit_irq(dev);
353
	mutex_unlock(&dev->struct_mutex);
Linus Torvalds's avatar
Linus Torvalds committed
354

355
	if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
Linus Torvalds's avatar
Linus Torvalds committed
356
		DRM_ERROR("copy_to_user\n");
Eric Anholt's avatar
Eric Anholt committed
357
		return -EFAULT;
Linus Torvalds's avatar
Linus Torvalds committed
358 359 360 361 362 363 364
	}

	return 0;
}

/* Doesn't need the hardware lock.
 */
365 366
int i915_irq_wait(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
Linus Torvalds's avatar
Linus Torvalds committed
367 368
{
	drm_i915_private_t *dev_priv = dev->dev_private;
369
	drm_i915_irq_wait_t *irqwait = data;
Linus Torvalds's avatar
Linus Torvalds committed
370 371

	if (!dev_priv) {
372
		DRM_ERROR("called with no initialization\n");
Eric Anholt's avatar
Eric Anholt committed
373
		return -EINVAL;
Linus Torvalds's avatar
Linus Torvalds committed
374 375
	}

376
	return i915_wait_irq(dev, irqwait->irq_seq);
Linus Torvalds's avatar
Linus Torvalds committed
377 378
}

379 380 381 382
/* Called from drm generic code, passed 'crtc' which
 * we use as a pipe index
 */
int i915_enable_vblank(struct drm_device *dev, int pipe)
383 384
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
385
	unsigned long irqflags;
386

387 388
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
	if (IS_I965G(dev))
389 390
		i915_enable_pipestat(dev_priv, pipe,
				     PIPE_START_VBLANK_INTERRUPT_ENABLE);
391
	else
392 393
		i915_enable_pipestat(dev_priv, pipe,
				     PIPE_VBLANK_INTERRUPT_ENABLE);
394
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
395 396 397
	return 0;
}

398 399 400 401
/* Called from drm generic code, passed 'crtc' which
 * we use as a pipe index
 */
void i915_disable_vblank(struct drm_device *dev, int pipe)
402 403
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
404
	unsigned long irqflags;
405

406
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
407 408 409
	i915_disable_pipestat(dev_priv, pipe,
			      PIPE_VBLANK_INTERRUPT_ENABLE |
			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
410
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
411 412
}

413 414
/* Set the vblank monitor pipe
 */
415 416
int i915_vblank_pipe_set(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
417 418 419 420
{
	drm_i915_private_t *dev_priv = dev->dev_private;

	if (!dev_priv) {
421
		DRM_ERROR("called with no initialization\n");
Eric Anholt's avatar
Eric Anholt committed
422
		return -EINVAL;
423 424
	}

425
	return 0;
426 427
}

428 429
int i915_vblank_pipe_get(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
430 431
{
	drm_i915_private_t *dev_priv = dev->dev_private;
432
	drm_i915_vblank_pipe_t *pipe = data;
433 434

	if (!dev_priv) {
435
		DRM_ERROR("called with no initialization\n");
Eric Anholt's avatar
Eric Anholt committed
436
		return -EINVAL;
437 438
	}

439
	pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
440

441 442 443
	return 0;
}

444 445 446
/**
 * Schedule buffer swap at given vertical blank.
 */
447 448
int i915_vblank_swap(struct drm_device *dev, void *data,
		     struct drm_file *file_priv)
449
{
450 451 452 453 454 455 456 457 458 459 460 461 462
	/* The delayed swap mechanism was fundamentally racy, and has been
	 * removed.  The model was that the client requested a delayed flip/swap
	 * from the kernel, then waited for vblank before continuing to perform
	 * rendering.  The problem was that the kernel might wake the client
	 * up before it dispatched the vblank swap (since the lock has to be
	 * held while touching the ringbuffer), in which case the client would
	 * clear and start the next frame before the swap occurred, and
	 * flicker would occur in addition to likely missing the vblank.
	 *
	 * In the absence of this ioctl, userland falls back to a correct path
	 * of waiting for a vblank, then dispatching the swap on its own.
	 * Context switching to userland and back is plenty fast enough for
	 * meeting the requirements of vblank swapping.
463
	 */
464
	return -EINVAL;
465 466
}

Linus Torvalds's avatar
Linus Torvalds committed
467 468
/* drm_dma.h hooks
*/
469
void i915_driver_irq_preinstall(struct drm_device * dev)
Linus Torvalds's avatar
Linus Torvalds committed
470 471 472
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;

473
	I915_WRITE(HWSTAM, 0xeffe);
474 475
	I915_WRITE(PIPEASTAT, 0);
	I915_WRITE(PIPEBSTAT, 0);
476
	I915_WRITE(IMR, 0xffffffff);
477
	I915_WRITE(IER, 0x0);
478
	(void) I915_READ(IER);
Linus Torvalds's avatar
Linus Torvalds committed
479 480
}

481
int i915_driver_irq_postinstall(struct drm_device *dev)
Linus Torvalds's avatar
Linus Torvalds committed
482 483
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
484
	int ret, num_pipes = 2;
Linus Torvalds's avatar
Linus Torvalds committed
485

486 487 488 489 490 491 492
	ret = drm_vblank_init(dev, num_pipes);
	if (ret)
		return ret;

	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;

	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
493

494 495 496 497 498 499 500 501 502 503 504
	/* Unmask the interrupts that we always want on. */
	dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;

	dev_priv->pipestat[0] = 0;
	dev_priv->pipestat[1] = 0;

	/* Disable pipe interrupt enables, clear pending pipe status */
	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
	/* Clear pending interrupt status */
	I915_WRITE(IIR, I915_READ(IIR));
505

506
	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
507
	I915_WRITE(IMR, dev_priv->irq_mask_reg);
508 509
	(void) I915_READ(IER);

510
	opregion_enable_asle(dev);
Linus Torvalds's avatar
Linus Torvalds committed
511
	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
512 513

	return 0;
Linus Torvalds's avatar
Linus Torvalds committed
514 515
}

516
void i915_driver_irq_uninstall(struct drm_device * dev)
Linus Torvalds's avatar
Linus Torvalds committed
517 518
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
519

Linus Torvalds's avatar
Linus Torvalds committed
520 521 522
	if (!dev_priv)
		return;

523 524 525
	dev_priv->vblank_pipe = 0;

	I915_WRITE(HWSTAM, 0xffffffff);
526 527
	I915_WRITE(PIPEASTAT, 0);
	I915_WRITE(PIPEBSTAT, 0);
528
	I915_WRITE(IMR, 0xffffffff);
529
	I915_WRITE(IER, 0x0);
530

531 532 533
	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
	I915_WRITE(IIR, I915_READ(IIR));
Linus Torvalds's avatar
Linus Torvalds committed
534
}