i915_irq.c 16.0 KB
Newer Older
D
Dave Airlie 已提交
1
/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*-
L
Linus Torvalds 已提交
2
 */
D
Dave Airlie 已提交
3
/*
L
Linus Torvalds 已提交
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.
 *
D
Dave Airlie 已提交
27
 */
L
Linus Torvalds 已提交
28 29 30 31 32

#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"
J
Jesse Barnes 已提交
33
#include "intel_drv.h"
L
Linus Torvalds 已提交
34 35 36

#define MAX_NOPID ((u32)~0)

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
/**
 * 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)
54

J
Jesse Barnes 已提交
55 56 57 58 59 60 61 62 63
#define I915_PIPE_VBLANK_STATUS	(PIPE_START_VBLANK_INTERRUPT_STATUS |\
				 PIPE_VBLANK_INTERRUPT_STATUS)

#define I915_PIPE_VBLANK_ENABLE	(PIPE_START_VBLANK_INTERRUPT_ENABLE |\
				 PIPE_VBLANK_INTERRUPT_ENABLE)

#define DRM_I915_VBLANK_PIPE_ALL	(DRM_I915_VBLANK_PIPE_A | \
					 DRM_I915_VBLANK_PIPE_B)

64
void
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
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);
	}
}

84 85 86 87 88 89 90
static inline u32
i915_pipestat(int pipe)
{
	if (pipe == 0)
		return PIPEASTAT;
	if (pipe == 1)
		return PIPEBSTAT;
91
	BUG();
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
}

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);
	}
}

119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
/**
 * 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;
}

140 141 142 143
/* 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)
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
{
	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;
}

177 178 179 180 181 182 183 184 185 186 187 188 189
u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;

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

	return I915_READ(reg);
}

L
Linus Torvalds 已提交
190 191
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
192
	struct drm_device *dev = (struct drm_device *) arg;
L
Linus Torvalds 已提交
193
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
194
	struct drm_i915_master_private *master_priv;
195 196
	u32 iir, new_iir;
	u32 pipea_stats, pipeb_stats;
197 198
	u32 vblank_status;
	u32 vblank_enable;
199
	int vblank = 0;
200
	unsigned long irqflags;
201 202
	int irq_received;
	int ret = IRQ_NONE;
203

204 205
	atomic_inc(&dev_priv->irq_received);

206
	iir = I915_READ(IIR);
207

208 209 210 211 212 213 214
	if (IS_I965G(dev)) {
		vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
		vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
	} else {
		vblank_status = I915_VBLANK_INTERRUPT_STATUS;
		vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
	}
215

216 217 218 219 220 221 222 223 224 225 226
	for (;;) {
		irq_received = iir != 0;

		/* Can't rely on pipestat interrupt bit in iir as it might
		 * have been cleared after the pipestat interrupt was received.
		 * It doesn't set the bit in iir again, but it still produces
		 * interrupts (for non-MSI).
		 */
		spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
		pipea_stats = I915_READ(PIPEASTAT);
		pipeb_stats = I915_READ(PIPEBSTAT);
J
Jesse Barnes 已提交
227

228 229 230
		/*
		 * Clear the PIPE(A|B)STAT regs before the IIR
		 */
231
		if (pipea_stats & 0x8000ffff) {
232
			I915_WRITE(PIPEASTAT, pipea_stats);
233
			irq_received = 1;
234
		}
L
Linus Torvalds 已提交
235

236
		if (pipeb_stats & 0x8000ffff) {
237
			I915_WRITE(PIPEBSTAT, pipeb_stats);
238
			irq_received = 1;
239
		}
240 241 242 243 244 245
		spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);

		if (!irq_received)
			break;

		ret = IRQ_HANDLED;
246

247 248
		I915_WRITE(IIR, iir);
		new_iir = I915_READ(IIR); /* Flush posted writes */
249

250 251 252 253 254 255
		if (dev->primary->master) {
			master_priv = dev->primary->master->driver_priv;
			if (master_priv->sarea_priv)
				master_priv->sarea_priv->last_dispatch =
					READ_BREADCRUMB(dev_priv);
		}
256

257 258 259 260
		if (iir & I915_USER_INTERRUPT) {
			dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
			DRM_WAKEUP(&dev_priv->irq_queue);
		}
261

262
		if (pipea_stats & vblank_status) {
263 264 265
			vblank++;
			drm_handle_vblank(dev, 0);
		}
266

267
		if (pipeb_stats & vblank_status) {
268 269 270
			vblank++;
			drm_handle_vblank(dev, 1);
		}
271

272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
		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;
292
	}
293

294
	return ret;
L
Linus Torvalds 已提交
295 296
}

297
static int i915_emit_irq(struct drm_device * dev)
L
Linus Torvalds 已提交
298 299
{
	drm_i915_private_t *dev_priv = dev->dev_private;
300
	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
L
Linus Torvalds 已提交
301 302 303 304
	RING_LOCALS;

	i915_kernel_lost_context(dev);

305
	DRM_DEBUG("\n");
L
Linus Torvalds 已提交
306

307
	dev_priv->counter++;
308
	if (dev_priv->counter > 0x7FFFFFFFUL)
309
		dev_priv->counter = 1;
310 311
	if (master_priv->sarea_priv)
		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
312

313
	BEGIN_LP_RING(4);
314
	OUT_RING(MI_STORE_DWORD_INDEX);
315
	OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
316
	OUT_RING(dev_priv->counter);
317
	OUT_RING(MI_USER_INTERRUPT);
L
Linus Torvalds 已提交
318
	ADVANCE_LP_RING();
D
Dave Airlie 已提交
319

320
	return dev_priv->counter;
L
Linus Torvalds 已提交
321 322
}

323
void i915_user_irq_get(struct drm_device *dev)
324 325
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
326
	unsigned long irqflags;
327

328
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
329 330
	if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
		i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
331
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
332 333
}

334
void i915_user_irq_put(struct drm_device *dev)
335 336
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
337
	unsigned long irqflags;
338

339
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
340 341 342
	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);
343
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
344 345
}

346
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
L
Linus Torvalds 已提交
347 348
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
349
	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
L
Linus Torvalds 已提交
350 351
	int ret = 0;

352
	DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
L
Linus Torvalds 已提交
353 354
		  READ_BREADCRUMB(dev_priv));

355
	if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
356 357
		if (master_priv->sarea_priv)
			master_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
L
Linus Torvalds 已提交
358
		return 0;
359
	}
L
Linus Torvalds 已提交
360

361 362
	if (master_priv->sarea_priv)
		master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
L
Linus Torvalds 已提交
363

364
	i915_user_irq_get(dev);
L
Linus Torvalds 已提交
365 366
	DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
		    READ_BREADCRUMB(dev_priv) >= irq_nr);
367
	i915_user_irq_put(dev);
L
Linus Torvalds 已提交
368

E
Eric Anholt 已提交
369
	if (ret == -EBUSY) {
370
		DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
L
Linus Torvalds 已提交
371 372 373
			  READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
	}

374 375 376
	return ret;
}

L
Linus Torvalds 已提交
377 378
/* Needs the lock as it touches the ring.
 */
379 380
int i915_irq_emit(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
L
Linus Torvalds 已提交
381 382
{
	drm_i915_private_t *dev_priv = dev->dev_private;
383
	drm_i915_irq_emit_t *emit = data;
L
Linus Torvalds 已提交
384 385
	int result;

386
	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
L
Linus Torvalds 已提交
387 388

	if (!dev_priv) {
389
		DRM_ERROR("called with no initialization\n");
E
Eric Anholt 已提交
390
		return -EINVAL;
L
Linus Torvalds 已提交
391
	}
392
	mutex_lock(&dev->struct_mutex);
L
Linus Torvalds 已提交
393
	result = i915_emit_irq(dev);
394
	mutex_unlock(&dev->struct_mutex);
L
Linus Torvalds 已提交
395

396
	if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
L
Linus Torvalds 已提交
397
		DRM_ERROR("copy_to_user\n");
E
Eric Anholt 已提交
398
		return -EFAULT;
L
Linus Torvalds 已提交
399 400 401 402 403 404 405
	}

	return 0;
}

/* Doesn't need the hardware lock.
 */
406 407
int i915_irq_wait(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
L
Linus Torvalds 已提交
408 409
{
	drm_i915_private_t *dev_priv = dev->dev_private;
410
	drm_i915_irq_wait_t *irqwait = data;
L
Linus Torvalds 已提交
411 412

	if (!dev_priv) {
413
		DRM_ERROR("called with no initialization\n");
E
Eric Anholt 已提交
414
		return -EINVAL;
L
Linus Torvalds 已提交
415 416
	}

417
	return i915_wait_irq(dev, irqwait->irq_seq);
L
Linus Torvalds 已提交
418 419
}

420 421 422 423
/* Called from drm generic code, passed 'crtc' which
 * we use as a pipe index
 */
int i915_enable_vblank(struct drm_device *dev, int pipe)
424 425
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
426
	unsigned long irqflags;
427 428 429 430 431 432
	int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
	u32 pipeconf;

	pipeconf = I915_READ(pipeconf_reg);
	if (!(pipeconf & PIPEACONF_ENABLE))
		return -EINVAL;
433

434 435
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
	if (IS_I965G(dev))
436 437
		i915_enable_pipestat(dev_priv, pipe,
				     PIPE_START_VBLANK_INTERRUPT_ENABLE);
438
	else
439 440
		i915_enable_pipestat(dev_priv, pipe,
				     PIPE_VBLANK_INTERRUPT_ENABLE);
441
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
442 443 444
	return 0;
}

445 446 447 448
/* Called from drm generic code, passed 'crtc' which
 * we use as a pipe index
 */
void i915_disable_vblank(struct drm_device *dev, int pipe)
449 450
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
451
	unsigned long irqflags;
452

453
	spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
454 455 456
	i915_disable_pipestat(dev_priv, pipe,
			      PIPE_VBLANK_INTERRUPT_ENABLE |
			      PIPE_START_VBLANK_INTERRUPT_ENABLE);
457
	spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
458 459
}

J
Jesse Barnes 已提交
460 461 462 463 464 465 466 467
void i915_enable_interrupt (struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	opregion_enable_asle(dev);
	dev_priv->irq_enabled = 1;
}


468 469
/* Set the vblank monitor pipe
 */
470 471
int i915_vblank_pipe_set(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
472 473 474 475
{
	drm_i915_private_t *dev_priv = dev->dev_private;

	if (!dev_priv) {
476
		DRM_ERROR("called with no initialization\n");
E
Eric Anholt 已提交
477
		return -EINVAL;
478 479
	}

480
	return 0;
481 482
}

483 484
int i915_vblank_pipe_get(struct drm_device *dev, void *data,
			 struct drm_file *file_priv)
485 486
{
	drm_i915_private_t *dev_priv = dev->dev_private;
487
	drm_i915_vblank_pipe_t *pipe = data;
488 489

	if (!dev_priv) {
490
		DRM_ERROR("called with no initialization\n");
E
Eric Anholt 已提交
491
		return -EINVAL;
492 493
	}

494
	pipe->pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
495

496 497 498
	return 0;
}

499 500 501
/**
 * Schedule buffer swap at given vertical blank.
 */
502 503
int i915_vblank_swap(struct drm_device *dev, void *data,
		     struct drm_file *file_priv)
504
{
505 506 507 508 509 510 511 512 513 514 515 516 517
	/* 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.
518
	 */
519
	return -EINVAL;
520 521
}

L
Linus Torvalds 已提交
522 523
/* drm_dma.h hooks
*/
524
void i915_driver_irq_preinstall(struct drm_device * dev)
L
Linus Torvalds 已提交
525 526 527
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;

J
Jesse Barnes 已提交
528 529
	atomic_set(&dev_priv->irq_received, 0);

530
	I915_WRITE(HWSTAM, 0xeffe);
531 532
	I915_WRITE(PIPEASTAT, 0);
	I915_WRITE(PIPEBSTAT, 0);
533
	I915_WRITE(IMR, 0xffffffff);
534
	I915_WRITE(IER, 0x0);
535
	(void) I915_READ(IER);
L
Linus Torvalds 已提交
536 537
}

538
int i915_driver_irq_postinstall(struct drm_device *dev)
L
Linus Torvalds 已提交
539 540
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
541 542 543 544

	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 */
545

546 547 548 549 550 551 552 553 554 555 556
	/* 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));
557

558
	I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
559
	I915_WRITE(IMR, dev_priv->irq_mask_reg);
560 561
	(void) I915_READ(IER);

562
	opregion_enable_asle(dev);
L
Linus Torvalds 已提交
563
	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
564 565

	return 0;
L
Linus Torvalds 已提交
566 567
}

568
void i915_driver_irq_uninstall(struct drm_device * dev)
L
Linus Torvalds 已提交
569 570
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
571

L
Linus Torvalds 已提交
572 573 574
	if (!dev_priv)
		return;

575 576 577
	dev_priv->vblank_pipe = 0;

	I915_WRITE(HWSTAM, 0xffffffff);
578 579
	I915_WRITE(PIPEASTAT, 0);
	I915_WRITE(PIPEBSTAT, 0);
580
	I915_WRITE(IMR, 0xffffffff);
581
	I915_WRITE(IER, 0x0);
582

583 584 585
	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
	I915_WRITE(IIR, I915_READ(IIR));
L
Linus Torvalds 已提交
586
}