11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
30d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie/*
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All Rights Reserved.
6bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
7bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * Permission is hereby granted, free of charge, to any person obtaining a
8bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * copy of this software and associated documentation files (the
9bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * "Software"), to deal in the Software without restriction, including
10bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * without limitation the rights to use, copy, modify, merge, publish,
11bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * distribute, sub license, and/or sell copies of the Software, and to
12bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * permit persons to whom the Software is furnished to do so, subject to
13bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * the following conditions:
14bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
15bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * The above copyright notice and this permission notice (including the
16bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * next paragraph) shall be included in all copies or substantial portions
17bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * of the Software.
18bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
19bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26bc54fd1ad3c5972be339a08528ab631326ed2b38Dave Airlie *
270d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie */
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drmP.h"
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "drm.h"
3179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "drm_crtc_helper.h"
32785b93ef8c309730c2de84ce9c229e40e2d01480Dave Airlie#include "drm_fb_helper.h"
3379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes#include "intel_drv.h"
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drm.h"
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "i915_drv.h"
361c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson#include "i915_trace.h"
3763ee41d794d9c555f84205517a68509848988760Eric Anholt#include "../../../platform/x86/intel_ips.h"
38dcdb167402cbdca1d021bdfa5f63995ee0a79317Jordan Crouse#include <linux/pci.h>
3928d520433b6375740990ab99d69b0d0067fd656bDave Airlie#include <linux/vgaarb.h>
40c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#include <linux/acpi.h>
41c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#include <linux/pnp.h>
426a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie#include <linux/vga_switcheroo.h>
435a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
44e0cd3608135b2ed8eddbe3fdf048d22e0593d836Paul Gortmaker#include <linux/module.h>
4544834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson#include <acpi/video.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
474cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilsonstatic void i915_write_hws_pga(struct drm_device *dev)
484cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson{
494cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson	drm_i915_private_t *dev_priv = dev->dev_private;
504cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson	u32 addr;
514cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson
524cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson	addr = dev_priv->status_page_dmah->busaddr;
534cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson	if (INTEL_INFO(dev)->gen >= 4)
544cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
554cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson	I915_WRITE(HWS_PGA, addr);
564cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson}
574cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson
58398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
59398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Sets up the hardware status page for devices that need a physical address
60398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * in the register.
61398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
623043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic int i915_init_phys_hws(struct drm_device *dev)
63398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
64398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
651ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson
66398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Program Hardware Status Page */
67398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	dev_priv->status_page_dmah =
68e6be8d9d17bd44061116f601fe2609b3ace7aa69Zhenyu Wang		drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE);
69398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
70398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!dev_priv->status_page_dmah) {
71398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		DRM_ERROR("Can not allocate hardware status page\n");
72398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		return -ENOMEM;
73398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
74398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
75f3234706a77bd6e1592ae71fb3268e04cb030dbaKeith Packard	memset_io((void __force __iomem *)dev_priv->status_page_dmah->vaddr,
76f3234706a77bd6e1592ae71fb3268e04cb030dbaKeith Packard		  0, PAGE_SIZE);
77398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
784cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson	i915_write_hws_pga(dev);
799b974cc17166d31afed2638d56bdbf9829afbfaaZhenyu Wang
808a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
81398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	return 0;
82398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
83398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
84398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/**
85398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Frees the hardware status page, whether it's a physical address or a virtual
86398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * address set up by the X Server.
87398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */
883043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic void i915_free_hws(struct drm_device *dev)
89398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{
90398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	drm_i915_private_t *dev_priv = dev->dev_private;
911ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	struct intel_ring_buffer *ring = LP_RING(dev_priv);
921ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson
93398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (dev_priv->status_page_dmah) {
94398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_pci_free(dev, dev_priv->status_page_dmah);
95398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		dev_priv->status_page_dmah = NULL;
96398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
97398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
981ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	if (ring->status_page.gfx_addr) {
991ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson		ring->status_page.gfx_addr = 0;
100398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		drm_core_ioremapfree(&dev_priv->hws_map, dev);
101398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
102398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
103398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Need to rewrite hardware status page */
104398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	I915_WRITE(HWS_PGA, 0x1ffff000);
105398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard}
106398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard
10784b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev)
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
1107c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv;
1111ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	struct intel_ring_buffer *ring = LP_RING(dev_priv);
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/*
11479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * We should never lose context on the ring with modesetting
11579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 * as we don't expose it to userspace
11679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	 */
11779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET))
11879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return;
11979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1208168bd48bb863c00747497aadf13884b2d69d287Chris Wilson	ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
1218168bd48bb863c00747497aadf13884b2d69d287Chris Wilson	ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ring->space = ring->head - (ring->tail + 8);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ring->space < 0)
1248187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai		ring->space += ring->size;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1267c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!dev->primary->master)
1277c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return;
1287c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
1297c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv = dev->primary->master->driver_priv;
1307c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (ring->head == ring->tail && master_priv->sarea_priv)
1317c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev)
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
136ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1371ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	int i;
1381ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Make sure interrupts are disabled here because the uninstall ioctl
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * may not have been called from userspace and after dev_private
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is freed, it's too late.
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
143ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->irq_enabled)
144b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie		drm_irq_uninstall(dev);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
146ee0c6bfbd602cdad2ab1780061b3b1a9108cbd6cDan Carpenter	mutex_lock(&dev->struct_mutex);
1471ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	for (i = 0; i < I915_NUM_RINGS; i++)
1481ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson		intel_cleanup_ring_buffer(&dev_priv->ring[i]);
149ee0c6bfbd602cdad2ab1780061b3b1a9108cbd6cDan Carpenter	mutex_unlock(&dev->struct_mutex);
150dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
151398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Clear the HWS virtual address at teardown */
152398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (I915_NEED_GFX_HWS(dev))
153398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		i915_free_hws(dev);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
158ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
160ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
1617c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
162e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson	int ret;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1643a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	master_priv->sarea = drm_getsarea(dev);
1653a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	if (master_priv->sarea) {
1663a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie		master_priv->sarea_priv = (drm_i915_sarea_t *)
1673a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie			((u8 *)master_priv->sarea->handle + init->sarea_priv_offset);
1683a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	} else {
1698a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui		DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n");
1703a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie	}
1713a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie
172673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	if (init->ring_size != 0) {
173e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson		if (LP_RING(dev_priv)->obj != NULL) {
174673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
175673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			DRM_ERROR("Client tried to initialize ringbuffer in "
176673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt				  "GEM mode\n");
177673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			return -EINVAL;
178673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
180e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson		ret = intel_render_ring_init_dri(dev,
181e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson						 init->ring_start,
182e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson						 init->ring_size);
183e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson		if (ret) {
184673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt			i915_dma_cleanup(dev);
185e8616b6ced6137085e6657cc63bc2fe3900b8616Chris Wilson			return ret;
186673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
189a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer	dev_priv->cpp = init->cpp;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->back_offset = init->back_offset;
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->front_offset = init->front_offset;
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->current_page = 0;
1937c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master_priv->sarea_priv)
1947c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->pf_current_page = 0;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow hardware batchbuffers unless told otherwise.
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_priv->allow_batchbuffer = 1;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev)
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
2061ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	struct intel_ring_buffer *ring = LP_RING(dev_priv);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2088a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("%s\n", __func__);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2108187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai	if (ring->map.handle == NULL) {
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("can not ioremap virtual address for"
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  " ring buffer\n");
21320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Program Hardware Status Page */
2178187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai	if (!ring->status_page.page_addr) {
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Can not find hardware status page\n");
21920caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2218a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("hw status page @ %p\n",
2228187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai				ring->status_page.page_addr);
2238187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai	if (ring->status_page.gfx_addr != 0)
22478501eac34f372bfbeb4e1d9de688c13efa916f6Chris Wilson		intel_ring_setup_status_page(ring);
225dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	else
2264cbf74ccf8362e99b2bdf1e66112a480c79ecacfChris Wilson		i915_write_hws_pga(dev);
2278187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai
2288a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
233c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data,
234c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
236c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_init_t *init = data;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int retcode = 0;
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
239c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (init->func) {
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_INIT_DMA:
241ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		retcode = i915_initialize(dev, init);
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_CLEANUP_DMA:
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retcode = i915_dma_cleanup(dev);
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_RESUME_DMA:
2470d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		retcode = i915_dma_resume(dev);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
25020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		retcode = -EINVAL;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retcode;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE.  These can be made stricter at any time.
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction.  It's important to get the size right as
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is.  Any illegal
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer.
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
266e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilsonstatic int validate_cmd(int cmd)
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (((cmd >> 29) & 0x7)) {
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x0:
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 23) & 0x3f) {
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x0:
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_NOOP */
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x4:
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;	/* MI_FLUSH */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;	/* disallow everything else */
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x1:
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;	/* reserved */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x2:
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (cmd & 0xff) + 2;	/* 2d commands */
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0x3:
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (((cmd >> 24) & 0x1f) <= 0x18)
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch ((cmd >> 24) & 0x1f) {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1c:
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 1;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1d:
291b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie			switch ((cmd >> 16) & 0xff) {
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x3:
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1f) + 2;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			case 0x4:
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xf) + 2;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			default:
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 2;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1e:
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cmd & (1 << 23))
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0xffff) + 1;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 1;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0x1f:
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((cmd & (1 << 23)) == 0)	/* inline vertices */
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return (cmd & 0x1ffff) + 2;
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (cmd & (1 << 17))	/* indirect random */
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((cmd & 0xffff) == 0)
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return 0;	/* unknown length, too hard */
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					return (((cmd & 0xffff) + 1) / 2) + 1;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return 2;	/* indirect sequential */
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
324201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtstatic int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
327e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int i, ret;
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	if ((dwords+1) * sizeof(int) >= LP_RING(dev_priv)->size - 8)
33020caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
331de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < dwords;) {
333e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		int sz = validate_cmd(buffer[i]);
334e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (sz == 0 || i + sz > dwords)
33520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt			return -EINVAL;
336e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		i += sz;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
339e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING((dwords+1)&~1);
340e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret)
341e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
342e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
343e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	for (i = 0; i < dwords; i++)
344e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(buffer[i]);
345de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	if (dwords & 1)
346de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie		OUT_RING(0);
347de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
348de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	ADVANCE_LP_RING();
349de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
353673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint
354673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholti915_emit_box(struct drm_device *dev,
355c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson	      struct drm_clip_rect *box,
356c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson	      int DR1, int DR4)
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
358e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
359e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson	if (box->y2 <= box->y1 || box->x2 <= box->x1 ||
362c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson	    box->y2 <= 0 || box->x2 <= 0) {
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Bad box %d,%d..%d,%d\n",
364c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson			  box->x1, box->y1, box->x2, box->y2);
36520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
368a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4) {
369e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ret = BEGIN_LP_RING(4);
370e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (ret)
371e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			return ret;
372e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
373c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
374c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson		OUT_RING((box->x1 & 0xffff) | (box->y1 << 16));
375c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson		OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16));
376c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
377c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	} else {
378e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ret = BEGIN_LP_RING(6);
379e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (ret)
380e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			return ret;
381e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
382c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(GFX_OP_DRAWRECT_INFO);
383c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR1);
384c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson		OUT_RING((box->x1 & 0xffff) | (box->y1 << 16));
385c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson		OUT_RING(((box->x2 - 1) & 0xffff) | ((box->y2 - 1) << 16));
386c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(DR4);
387c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane		OUT_RING(0);
388c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane	}
389e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ADVANCE_LP_RING();
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
394c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ
395c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places:
396c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */
397c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane
39884b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev)
399de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{
400de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	drm_i915_private_t *dev_priv = dev->dev_private;
4017c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
402de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
403c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	dev_priv->counter++;
404af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->counter > 0x7FFFFFFFUL)
405c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg		dev_priv->counter = 0;
4067c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (master_priv->sarea_priv)
4077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		master_priv->sarea_priv->last_enqueue = dev_priv->counter;
408de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
409e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (BEGIN_LP_RING(4) == 0) {
410e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(MI_STORE_DWORD_INDEX);
411e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
412e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(dev_priv->counter);
413e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(0);
414e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ADVANCE_LP_RING();
415e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
416de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie}
417de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie
41884b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev,
419201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   drm_i915_cmdbuffer_t *cmd,
420201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   struct drm_clip_rect *cliprects,
421201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				   void *cmdbuf)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = cmd->num_cliprects;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i = 0, count, ret;
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cmd->sz & 0x3) {
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
42820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
437c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson			ret = i915_emit_box(dev, &cliprects[i],
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					    cmd->DR1, cmd->DR4);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
443201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret)
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return ret;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
448de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie	i915_emit_breadcrumb(dev);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev,
453201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     drm_i915_batchbuffer_t * batch,
454201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     struct drm_clip_rect *cliprects)
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
456e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int nbox = batch->num_cliprects;
458e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int i, count, ret;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((batch->start | batch->used) & 0x7) {
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("alignment");
46220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = nbox ? nbox : 1;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < count; i++) {
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i < nbox) {
470c4e7a4146798ce22c229dd21ed31f59f07c4119eChris Wilson			ret = i915_emit_box(dev, &cliprects[i],
471e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson					    batch->DR1, batch->DR4);
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (ret)
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return ret;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4760790d5e148c0747499742a3c09ba5f1c07f9ed0dKeith Packard		if (!IS_I830(dev) && !IS_845G(dev)) {
477e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			ret = BEGIN_LP_RING(2);
478e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			if (ret)
479e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson				return ret;
480e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
481a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson			if (INTEL_INFO(dev)->gen >= 4) {
48221f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965);
48321f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start);
48421f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			} else {
48521f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
48621f16289270447673a7263ccc0b22d562fb01ecbDave Airlie				OUT_RING(batch->start | MI_BATCH_NON_SECURE);
48721f16289270447673a7263ccc0b22d562fb01ecbDave Airlie			}
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
489e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			ret = BEGIN_LP_RING(4);
490e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			if (ret)
491e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson				return ret;
492e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(MI_BATCH_BUFFER);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start | MI_BATCH_NON_SECURE);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(batch->start + batch->used - 4);
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			OUT_RING(0);
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
498e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ADVANCE_LP_RING();
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011cafd34731cd14e5a72edaf0f41717c8126cfce9Zou Nan hai
502f00a3ddf91d596bece5fa31e8ce2e8a3b4c0623bChris Wilson	if (IS_G4X(dev) || IS_GEN5(dev)) {
503e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		if (BEGIN_LP_RING(2) == 0) {
504e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			OUT_RING(MI_FLUSH | MI_NO_WRITE_FLUSH | MI_INVALIDATE_ISP);
505e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			OUT_RING(MI_NOOP);
506e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson			ADVANCE_LP_RING();
507e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		}
5081cafd34731cd14e5a72edaf0f41717c8126cfce9Zou Nan hai	}
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
510e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	i915_emit_breadcrumb(dev);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
514af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev)
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
5177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv =
5187c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		dev->primary->master->driver_priv;
519e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	int ret;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5217c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv->sarea_priv)
522c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg		return -EINVAL;
523c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg
5248a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n",
525be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			  __func__,
526be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			 dev_priv->current_page,
527be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			 master_priv->sarea_priv->pf_current_page);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
529af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	i915_kernel_lost_context(dev);
530af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie
531e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	ret = BEGIN_LP_RING(10);
532e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (ret)
533e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		return ret;
534e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
535585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes	OUT_RING(MI_FLUSH | MI_READ_FLUSH);
536af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
538af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
539af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
540af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	if (dev_priv->current_page == 0) {
541af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->back_offset);
542af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 1;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
544af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		OUT_RING(dev_priv->front_offset);
545af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie		dev_priv->current_page = 0;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
547af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
549af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
550af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	OUT_RING(0);
551e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson
552af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	ADVANCE_LP_RING();
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5547c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv->sarea_priv->last_enqueue = dev_priv->counter++;
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
556e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	if (BEGIN_LP_RING(4) == 0) {
557e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(MI_STORE_DWORD_INDEX);
558e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
559e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(dev_priv->counter);
560e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		OUT_RING(0);
561e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson		ADVANCE_LP_RING();
562e1f99ce6cac3b6a95551642be5ddb5d9c46bea76Chris Wilson	}
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5647c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master_priv->sarea_priv->pf_current_page = dev_priv->current_page;
565af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie	return 0;
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5681ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilsonstatic int i915_quiescent(struct drm_device *dev)
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5701ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	struct intel_ring_buffer *ring = LP_RING(dev->dev_private);
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i915_kernel_lost_context(dev);
57396f298aa9c9fc9b7c8a2ebaf8c195d178f570e09Ben Widawsky	return intel_wait_ring_idle(ring);
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
576c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data,
577c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
579546b0974c39657017407c86fe79811100b60700dEric Anholt	int ret;
580546b0974c39657017407c86fe79811100b60700dEric Anholt
581546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
583546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
584546b0974c39657017407c86fe79811100b60700dEric Anholt	ret = i915_quiescent(dev);
585546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
586546b0974c39657017407c86fe79811100b60700dEric Anholt
587546b0974c39657017407c86fe79811100b60700dEric Anholt	return ret;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
590c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data,
591c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			    struct drm_file *file_priv)
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
5947c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
5967c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    master_priv->sarea_priv;
597c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_batchbuffer_t *batch = data;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
599201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect *cliprects = NULL;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv->allow_batchbuffer) {
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("Batchbuffer ioctl disabled\n");
60320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6068a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n",
607be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			batch->start, batch->used, batch->num_cliprects);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
609546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch->num_cliprects < 0)
612201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -EINVAL;
613201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
614201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch->num_cliprects) {
6159a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		cliprects = kcalloc(batch->num_cliprects,
6169a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt				    sizeof(struct drm_clip_rect),
6179a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt				    GFP_KERNEL);
618201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		if (cliprects == NULL)
619201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			return -ENOMEM;
620201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
621201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = copy_from_user(cliprects, batch->cliprects,
622201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     batch->num_cliprects *
623201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     sizeof(struct drm_clip_rect));
6249927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter		if (ret != 0) {
6259927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter			ret = -EFAULT;
626201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_free;
6279927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter		}
628201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	}
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
630546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
631201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
632546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
634c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	if (sarea_priv)
6350baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
636201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
637201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_free:
6389a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(cliprects);
639201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
643c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data,
644c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
6477c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
6497c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	    master_priv->sarea_priv;
650c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_cmdbuffer_t *cmdbuf = data;
651201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	struct drm_clip_rect *cliprects = NULL;
652201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	void *batch_data;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6558a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
656be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao			cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
658546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
660201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (cmdbuf->num_cliprects < 0)
661201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -EINVAL;
662201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
6639a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	batch_data = kmalloc(cmdbuf->sz, GFP_KERNEL);
664201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (batch_data == NULL)
665201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		return -ENOMEM;
666201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
667201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
6689927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter	if (ret != 0) {
6699927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter		ret = -EFAULT;
670201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		goto fail_batch_free;
6719927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter	}
672201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
673201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	if (cmdbuf->num_cliprects) {
6749a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt		cliprects = kcalloc(cmdbuf->num_cliprects,
6759a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt				    sizeof(struct drm_clip_rect), GFP_KERNEL);
676a40e8d3139e9eb54bf1d29f91639a6c5e05f652eOwain Ainsworth		if (cliprects == NULL) {
677a40e8d3139e9eb54bf1d29f91639a6c5e05f652eOwain Ainsworth			ret = -ENOMEM;
678201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_batch_free;
679a40e8d3139e9eb54bf1d29f91639a6c5e05f652eOwain Ainsworth		}
680201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
681201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt		ret = copy_from_user(cliprects, cmdbuf->cliprects,
682201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     cmdbuf->num_cliprects *
683201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt				     sizeof(struct drm_clip_rect));
6849927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter		if (ret != 0) {
6859927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter			ret = -EFAULT;
686201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt			goto fail_clip_free;
6879927a403ca8c97798129953fa9cbb5dc259c7cb9Dan Carpenter		}
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
690546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
691201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
692546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
695355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wright		goto fail_clip_free;
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
698c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg	if (sarea_priv)
6990baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard		sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
700201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
701201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_clip_free:
7029a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(cliprects);
703355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wrightfail_batch_free:
7049a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(batch_data);
705201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt
706201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt	return ret;
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
709c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data,
710c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			  struct drm_file *file_priv)
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
712546b0974c39657017407c86fe79811100b60700dEric Anholt	int ret;
713546b0974c39657017407c86fe79811100b60700dEric Anholt
7148a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("%s\n", __func__);
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
716546b0974c39657017407c86fe79811100b60700dEric Anholt	RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
718546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_lock(&dev->struct_mutex);
719546b0974c39657017407c86fe79811100b60700dEric Anholt	ret = i915_dispatch_flip(dev);
720546b0974c39657017407c86fe79811100b60700dEric Anholt	mutex_unlock(&dev->struct_mutex);
721546b0974c39657017407c86fe79811100b60700dEric Anholt
722546b0974c39657017407c86fe79811100b60700dEric Anholt	return ret;
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
725c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data,
726c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
729c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_getparam_t *param = data;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int value;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
7333e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
73420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
737c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_IRQ_ACTIVE:
7390a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes		value = dev->pdev->irq ? 1 : 0;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_PARAM_ALLOW_BATCHBUFFER:
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		value = dev_priv->allow_batchbuffer ? 1 : 0;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
7440d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie	case I915_PARAM_LAST_DISPATCH:
7450d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		value = READ_BREADCRUMB(dev_priv);
7460d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie		break;
747ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg	case I915_PARAM_CHIPSET_ID:
748ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		value = dev->pci_device;
749ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg		break;
750673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	case I915_PARAM_HAS_GEM:
751ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie		value = dev_priv->has_gem;
752673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		break;
7530f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes	case I915_PARAM_NUM_FENCES_AVAIL:
7540f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		value = dev_priv->num_fence_regs - dev_priv->fence_reg_start;
7550f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		break;
75602e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter	case I915_PARAM_HAS_OVERLAY:
75702e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		value = dev_priv->overlay ? 1 : 0;
75802e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		break;
759e9560f7cb20722e0e7db46bbb6f43c2194a238d5Jesse Barnes	case I915_PARAM_HAS_PAGEFLIPPING:
760e9560f7cb20722e0e7db46bbb6f43c2194a238d5Jesse Barnes		value = 1;
761e9560f7cb20722e0e7db46bbb6f43c2194a238d5Jesse Barnes		break;
76276446cac68568fc7f5168a27deaf803ed22a4360Jesse Barnes	case I915_PARAM_HAS_EXECBUF2:
76376446cac68568fc7f5168a27deaf803ed22a4360Jesse Barnes		/* depends on GEM */
76476446cac68568fc7f5168a27deaf803ed22a4360Jesse Barnes		value = dev_priv->has_gem;
76576446cac68568fc7f5168a27deaf803ed22a4360Jesse Barnes		break;
766e3a815fcd38043b8f1bb526123d8ab6ae01deb77Zou Nan hai	case I915_PARAM_HAS_BSD:
767e3a815fcd38043b8f1bb526123d8ab6ae01deb77Zou Nan hai		value = HAS_BSD(dev);
768e3a815fcd38043b8f1bb526123d8ab6ae01deb77Zou Nan hai		break;
769549f7365820a212a1cfd0871d377b1ad0d1e5723Chris Wilson	case I915_PARAM_HAS_BLT:
770549f7365820a212a1cfd0871d377b1ad0d1e5723Chris Wilson		value = HAS_BLT(dev);
771549f7365820a212a1cfd0871d377b1ad0d1e5723Chris Wilson		break;
772a00b10c360b35d6431a94cbf130a4e162870d661Chris Wilson	case I915_PARAM_HAS_RELAXED_FENCING:
773a00b10c360b35d6431a94cbf130a4e162870d661Chris Wilson		value = 1;
774a00b10c360b35d6431a94cbf130a4e162870d661Chris Wilson		break;
775bbf0c6b3620b3872929ef7d3c392ce436889110fDaniel Vetter	case I915_PARAM_HAS_COHERENT_RINGS:
776bbf0c6b3620b3872929ef7d3c392ce436889110fDaniel Vetter		value = 1;
777bbf0c6b3620b3872929ef7d3c392ce436889110fDaniel Vetter		break;
77872bfa19c8deb4d1db5ad068c34fd580cb295cbe8Chris Wilson	case I915_PARAM_HAS_EXEC_CONSTANTS:
77972bfa19c8deb4d1db5ad068c34fd580cb295cbe8Chris Wilson		value = INTEL_INFO(dev)->gen >= 4;
78072bfa19c8deb4d1db5ad068c34fd580cb295cbe8Chris Wilson		break;
781271d81b84171d84723357ae6d172ec16b0d8139cChris Wilson	case I915_PARAM_HAS_RELAXED_DELTA:
782271d81b84171d84723357ae6d172ec16b0d8139cChris Wilson		value = 1;
783271d81b84171d84723357ae6d172ec16b0d8139cChris Wilson		break;
784ae662d31264979e52581bd2573bf0b82812f52abEric Anholt	case I915_PARAM_HAS_GEN7_SOL_RESET:
785ae662d31264979e52581bd2573bf0b82812f52abEric Anholt		value = 1;
786ae662d31264979e52581bd2573bf0b82812f52abEric Anholt		break;
7873d29b842e58fbca2c13a9f458fddbaa535c6e578Eugeni Dodonov	case I915_PARAM_HAS_LLC:
7883d29b842e58fbca2c13a9f458fddbaa535c6e578Eugeni Dodonov		value = HAS_LLC(dev);
7893d29b842e58fbca2c13a9f458fddbaa535c6e578Eugeni Dodonov		break;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
7918a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
79276446cac68568fc7f5168a27deaf803ed22a4360Jesse Barnes				 param->param);
79320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
796c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) {
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DRM_ERROR("DRM_COPY_TO_USER failed\n");
79820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EFAULT;
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
804c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data,
805c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt			 struct drm_file *file_priv)
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	drm_i915_private_t *dev_priv = dev->dev_private;
808c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_setparam_t *param = data;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev_priv) {
8113e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
81220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
815c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	switch (param->param) {
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_USE_MI_BATCHBUFFER_START:
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY:
819c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->tex_lru_log_granularity = param->value;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case I915_SETPARAM_ALLOW_BATCHBUFFER:
822c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt		dev_priv->allow_batchbuffer = param->value;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8240f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes	case I915_SETPARAM_NUM_USED_FENCES:
8250f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		if (param->value > dev_priv->num_fence_regs ||
8260f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		    param->value < 0)
8270f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes			return -EINVAL;
8280f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		/* Userspace can use first N regs */
8290f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		dev_priv->fence_reg_start = param->value;
8300f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes		break;
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
8328a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui		DRM_DEBUG_DRIVER("unknown parameter %d\n",
833be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao					param->param);
83420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
840c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data,
841c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt				struct drm_file *file_priv)
842dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{
843dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	drm_i915_private_t *dev_priv = dev->dev_private;
844c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt	drm_i915_hws_addr_t *hws = data;
8451ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	struct intel_ring_buffer *ring = LP_RING(dev_priv);
846b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang
847b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang	if (!I915_NEED_GFX_HWS(dev))
848b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang		return -EINVAL;
849dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
850dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (!dev_priv) {
8513e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh		DRM_ERROR("called with no initialization\n");
85220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -EINVAL;
853dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
854dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
85579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
85679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		WARN(1, "tried to set status page when mode setting active\n");
85779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		return 0;
85879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
85979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
8608a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr);
861c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt
8628187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai	ring->status_page.gfx_addr = hws->addr & (0x1ffff<<12);
863dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
8648b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt	dev_priv->hws_map.offset = dev->agp->base + hws->addr;
865dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.size = 4*1024;
866dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.type = 0;
867dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.flags = 0;
868dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	dev_priv->hws_map.mtrr = 0;
869dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
870dd0910b3c71b253c08111110f0399b924a8d5853Dave Airlie	drm_core_ioremap_wc(&dev_priv->hws_map, dev);
871dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	if (dev_priv->hws_map.handle == NULL) {
872dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		i915_dma_cleanup(dev);
873e20f9c64c79e2282f9eb531509181965ec8f0a92Eric Anholt		ring->status_page.gfx_addr = 0;
874dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu		DRM_ERROR("can not ioremap virtual address for"
875dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu				" G33 hw status page\n");
87620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt		return -ENOMEM;
877dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	}
878311bd68e024f9006db66cbadc3bd9f62fd663f4bChris Wilson	ring->status_page.page_addr =
879311bd68e024f9006db66cbadc3bd9f62fd663f4bChris Wilson		(void __force __iomem *)dev_priv->hws_map.handle;
880311bd68e024f9006db66cbadc3bd9f62fd663f4bChris Wilson	memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
8818187a2b70e34c727a06617441f74f202b6fefaf9Zou Nan hai	I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
882dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
8838a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
884e20f9c64c79e2282f9eb531509181965ec8f0a92Eric Anholt			 ring->status_page.gfx_addr);
8858a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("load hws at %p\n",
886e20f9c64c79e2282f9eb531509181965ec8f0a92Eric Anholt			 ring->status_page.page_addr);
887dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu	return 0;
888dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu}
889dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu
890ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airliestatic int i915_get_bridge_dev(struct drm_device *dev)
891ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie{
892ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	struct drm_i915_private *dev_priv = dev->dev_private;
893ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie
8940206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));
895ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	if (!dev_priv->bridge_dev) {
896ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		DRM_ERROR("bridge device not found\n");
897ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		return -1;
898ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	}
899ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	return 0;
900ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie}
901ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie
902c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#define MCHBAR_I915 0x44
903c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#define MCHBAR_I965 0x48
904c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#define MCHBAR_SIZE (4*4096)
905c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
906c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#define DEVEN_REG 0x54
907c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#define   DEVEN_MCHBAR_EN (1 << 28)
908c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
909c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang/* Allocate space for the MCH regs if needed, return nonzero on error */
910c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wangstatic int
911c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wangintel_alloc_mchbar_resource(struct drm_device *dev)
912c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang{
913c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	drm_i915_private_t *dev_priv = dev->dev_private;
914a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	int reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
915c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	u32 temp_lo, temp_hi = 0;
916c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	u64 mchbar_addr;
917a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson	int ret;
918c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
919a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4)
920c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_read_config_dword(dev_priv->bridge_dev, reg + 4, &temp_hi);
921c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	pci_read_config_dword(dev_priv->bridge_dev, reg, &temp_lo);
922c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	mchbar_addr = ((u64)temp_hi << 32) | temp_lo;
923c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
924c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	/* If ACPI doesn't have it, assume we need to allocate it ourselves */
925c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#ifdef CONFIG_PNP
926c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (mchbar_addr &&
927a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson	    pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE))
928a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson		return 0;
929c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang#endif
930c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
931c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	/* Get some space for it */
932a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson	dev_priv->mch_res.name = "i915 MCHBAR";
933a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson	dev_priv->mch_res.flags = IORESOURCE_MEM;
934a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson	ret = pci_bus_alloc_resource(dev_priv->bridge_dev->bus,
935a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson				     &dev_priv->mch_res,
936c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang				     MCHBAR_SIZE, MCHBAR_SIZE,
937c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang				     PCIBIOS_MIN_MEM,
938a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson				     0, pcibios_align_resource,
939c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang				     dev_priv->bridge_dev);
940c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (ret) {
941c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		DRM_DEBUG_DRIVER("failed bus alloc: %d\n", ret);
942c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		dev_priv->mch_res.start = 0;
943a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson		return ret;
944c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	}
945c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
946a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	if (INTEL_INFO(dev)->gen >= 4)
947c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_write_config_dword(dev_priv->bridge_dev, reg + 4,
948c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang				       upper_32_bits(dev_priv->mch_res.start));
949c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
950c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	pci_write_config_dword(dev_priv->bridge_dev, reg,
951c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			       lower_32_bits(dev_priv->mch_res.start));
952a25c25c2a2aa55e609099a9f74453c518aec29a6Chris Wilson	return 0;
953c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang}
954c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
955c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang/* Setup MCHBAR if possible, return true if we should disable it again */
956c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wangstatic void
957c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wangintel_setup_mchbar(struct drm_device *dev)
958c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang{
959c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	drm_i915_private_t *dev_priv = dev->dev_private;
960a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
961c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	u32 temp;
962c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	bool enabled;
963c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
964c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	dev_priv->mchbar_need_disable = false;
965c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
966c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (IS_I915G(dev) || IS_I915GM(dev)) {
967c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
968c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		enabled = !!(temp & DEVEN_MCHBAR_EN);
969c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	} else {
970c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
971c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		enabled = temp & 1;
972c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	}
973c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
974c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	/* If it's already enabled, don't have to do anything */
975c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (enabled)
976c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		return;
977c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
978c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (intel_alloc_mchbar_resource(dev))
979c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		return;
980c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
981c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	dev_priv->mchbar_need_disable = true;
982c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
983c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	/* Space is allocated or reserved, so enable it. */
984c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (IS_I915G(dev) || IS_I915GM(dev)) {
985c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG,
986c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang				       temp | DEVEN_MCHBAR_EN);
987c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	} else {
988c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
989c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp | 1);
990c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	}
991c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang}
992c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
993c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wangstatic void
994c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wangintel_teardown_mchbar(struct drm_device *dev)
995c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang{
996c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	drm_i915_private_t *dev_priv = dev->dev_private;
997a6c45cf013a57e32ddae43dd4ac911eb4a3919fdChris Wilson	int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915;
998c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	u32 temp;
999c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
1000c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (dev_priv->mchbar_need_disable) {
1001c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		if (IS_I915G(dev) || IS_I915GM(dev)) {
1002c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			pci_read_config_dword(dev_priv->bridge_dev, DEVEN_REG, &temp);
1003c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			temp &= ~DEVEN_MCHBAR_EN;
1004c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			pci_write_config_dword(dev_priv->bridge_dev, DEVEN_REG, temp);
1005c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		} else {
1006c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			pci_read_config_dword(dev_priv->bridge_dev, mchbar_reg, &temp);
1007c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			temp &= ~1;
1008c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang			pci_write_config_dword(dev_priv->bridge_dev, mchbar_reg, temp);
1009c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		}
1010c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	}
1011c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
1012c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	if (dev_priv->mch_res.start)
1013c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang		release_resource(&dev_priv->mch_res);
1014c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang}
1015c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
10168082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_ADDRESS_MASK		0xfffff000
10178082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_ADDRESS_MASK_HIGH		0x000000f0 /* i915+ */
10188082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_UNCACHED	(0 << 1)
10198082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_DCACHE		(1 << 1) /* i830 only */
10208082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_CACHED		(3 << 1)
10218082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_MASK		(3 << 1)
10228082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_VALID			(1 << 0)
10238082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10248082400327d8d2ca54254b593644942bed0edd25Jesse Barnes/**
1025fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson * i915_stolen_to_phys - take an offset into stolen memory and turn it into
1026fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson *                       a physical one
10278082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * @dev: drm device
1028fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson * @offset: address to translate
10298082400327d8d2ca54254b593644942bed0edd25Jesse Barnes *
1030fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson * Some chip functions require allocations from stolen space and need the
1031fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson * physical address of the memory in question.
10328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes */
1033fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilsonstatic unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset)
10348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{
1035fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
1036fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	struct pci_dev *pdev = dev_priv->bridge_dev;
1037fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	u32 base;
1038fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson
1039fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson#if 0
1040fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	/* On the machines I have tested the Graphics Base of Stolen Memory
1041fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	 * is unreliable, so compute the base by subtracting the stolen memory
1042fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	 * from the Top of Low Usable DRAM which is where the BIOS places
1043fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	 * the graphics stolen memory.
1044fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	 */
1045fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
1046fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		/* top 32bits are reserved = 0 */
1047fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		pci_read_config_dword(pdev, 0xA4, &base);
10488082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	} else {
1049fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		/* XXX presume 8xx is the same as i915 */
1050fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base);
1051fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	}
1052fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson#else
1053fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) {
1054fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		u16 val;
1055fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		pci_read_config_word(pdev, 0xb0, &val);
1056fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		base = val >> 4 << 20;
1057fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	} else {
1058fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		u8 val;
1059fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		pci_read_config_byte(pdev, 0x9c, &val);
1060fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		base = val >> 3 << 27;
10618082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
1062c64f7ba5f1006d8c20eacafecf98d4d00a6902a0Chris Wilson	base -= dev_priv->mm.gtt->stolen_size;
1063fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson#endif
10648082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
1065fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	return base + offset;
10668082400327d8d2ca54254b593644942bed0edd25Jesse Barnes}
10678082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10688082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic void i915_warn_stolen(struct drm_device *dev)
10698082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{
10708082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_ERROR("not enough stolen space for compressed buffer, disabling\n");
10718082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	DRM_ERROR("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n");
10728082400327d8d2ca54254b593644942bed0edd25Jesse Barnes}
10738082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10748082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic void i915_setup_compression(struct drm_device *dev, int size)
10758082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{
10768082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
1077132b6aab90d2673af67c414878da241a197e00fbPrarit Bhargava	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb);
107829bd0ae25f8cb96b63560c2cbccec77b425e1603Andrew Morton	unsigned long cfb_base;
107929bd0ae25f8cb96b63560c2cbccec77b425e1603Andrew Morton	unsigned long ll_base = 0;
10808082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
108143a9539fa9e780f16c0d1e4bc91a2701f1ce178fChris Wilson	/* Just in case the BIOS is doing something questionable. */
108243a9539fa9e780f16c0d1e4bc91a2701f1ce178fChris Wilson	intel_disable_fbc(dev);
108343a9539fa9e780f16c0d1e4bc91a2701f1ce178fChris Wilson
1084fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0);
1085fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	if (compressed_fb)
1086fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);
1087fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	if (!compressed_fb)
1088fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		goto err;
10898082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
1090fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	cfb_base = i915_stolen_to_phys(dev, compressed_fb->start);
1091fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	if (!cfb_base)
1092fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		goto err_fb;
10938082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
10949c04f015ebc2cc2cca5a4a576deb82a311578edcYuanhan Liu	if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) {
1095fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,
1096fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson						    4096, 4096, 0);
1097fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		if (compressed_llb)
1098fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson			compressed_llb = drm_mm_get_block(compressed_llb,
1099fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson							  4096, 4096);
1100fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		if (!compressed_llb)
1101fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson			goto err_fb;
110274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes
1103fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		ll_base = i915_stolen_to_phys(dev, compressed_llb->start);
1104fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		if (!ll_base)
1105fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson			goto err_llb;
11068082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11078082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
11088082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	dev_priv->cfb_size = size;
11098082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
111020bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes	dev_priv->compressed_fb = compressed_fb;
11119c04f015ebc2cc2cca5a4a576deb82a311578edcYuanhan Liu	if (HAS_PCH_SPLIT(dev))
1112b52eb4dcab23fe0c52a437276258e0afcf913ef5Zhao Yakui		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
1113b52eb4dcab23fe0c52a437276258e0afcf913ef5Zhao Yakui	else if (IS_GM45(dev)) {
111474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
111574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes	} else {
111674dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		I915_WRITE(FBC_CFB_BASE, cfb_base);
111774dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes		I915_WRITE(FBC_LL_BASE, ll_base);
111820bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes		dev_priv->compressed_llb = compressed_llb;
11198082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
11208082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
1121fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n",
1122fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		      cfb_base, ll_base, size >> 20);
1123fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	return;
1124fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson
1125fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilsonerr_llb:
1126fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	drm_mm_put_block(compressed_llb);
1127fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilsonerr_fb:
1128fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	drm_mm_put_block(compressed_fb);
1129fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilsonerr:
1130fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL;
1131fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	i915_warn_stolen(dev);
11328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes}
11338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
113420bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnesstatic void i915_cleanup_compression(struct drm_device *dev)
113520bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes{
113620bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
113720bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes
113820bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes	drm_mm_put_block(dev_priv->compressed_fb);
1139aebf0dafee1a0a22b3d25db8107c6479db4aaebeJesse Barnes	if (dev_priv->compressed_llb)
114020bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes		drm_mm_put_block(dev_priv->compressed_llb);
114120bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes}
114220bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes
114328d520433b6375740990ab99d69b0d0067fd656bDave Airlie/* true = enable decode, false = disable decoder */
114428d520433b6375740990ab99d69b0d0067fd656bDave Airliestatic unsigned int i915_vga_set_decode(void *cookie, bool state)
114528d520433b6375740990ab99d69b0d0067fd656bDave Airlie{
114628d520433b6375740990ab99d69b0d0067fd656bDave Airlie	struct drm_device *dev = cookie;
114728d520433b6375740990ab99d69b0d0067fd656bDave Airlie
114828d520433b6375740990ab99d69b0d0067fd656bDave Airlie	intel_modeset_vga_set_state(dev, state);
114928d520433b6375740990ab99d69b0d0067fd656bDave Airlie	if (state)
115028d520433b6375740990ab99d69b0d0067fd656bDave Airlie		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
115128d520433b6375740990ab99d69b0d0067fd656bDave Airlie		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
115228d520433b6375740990ab99d69b0d0067fd656bDave Airlie	else
115328d520433b6375740990ab99d69b0d0067fd656bDave Airlie		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
115428d520433b6375740990ab99d69b0d0067fd656bDave Airlie}
115528d520433b6375740990ab99d69b0d0067fd656bDave Airlie
11566a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airliestatic void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
11576a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie{
11586a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	struct drm_device *dev = pci_get_drvdata(pdev);
11596a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };
11606a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	if (state == VGA_SWITCHEROO_ON) {
1161fbf81762e385d3d45acad057b654d56972acf58cDave Airlie		printk(KERN_INFO "i915: switched on\n");
11625bcf719b7db0f9366cedaf102b081f99b1c325aeDave Airlie		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
11636a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		/* i915 resume handler doesn't set to D0 */
11646a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		pci_set_power_state(dev->pdev, PCI_D0);
11656a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		i915_resume(dev);
11665bcf719b7db0f9366cedaf102b081f99b1c325aeDave Airlie		dev->switch_power_state = DRM_SWITCH_POWER_ON;
11676a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	} else {
11686a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		printk(KERN_ERR "i915: switched off\n");
11695bcf719b7db0f9366cedaf102b081f99b1c325aeDave Airlie		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
11706a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		i915_suspend(dev, pmm);
11715bcf719b7db0f9366cedaf102b081f99b1c325aeDave Airlie		dev->switch_power_state = DRM_SWITCH_POWER_OFF;
11726a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	}
11736a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie}
11746a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie
11756a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airliestatic bool i915_switcheroo_can_switch(struct pci_dev *pdev)
11766a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie{
11776a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	struct drm_device *dev = pci_get_drvdata(pdev);
11786a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	bool can_switch;
11796a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie
11806a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	spin_lock(&dev->count_lock);
11816a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	can_switch = (dev->open_count == 0);
11826a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	spin_unlock(&dev->count_lock);
11836a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	return can_switch;
11846a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie}
11856a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie
1186650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetterstatic bool
1187650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetterintel_enable_ppgtt(struct drm_device *dev)
1188650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter{
1189650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter	if (i915_enable_ppgtt >= 0)
1190650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter		return i915_enable_ppgtt;
1191650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter
1192650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter#ifdef CONFIG_INTEL_IOMMU
1193650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter	/* Disable ppgtt on SNB if VT-d is on. */
1194650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped)
1195650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter		return false;
1196650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter#endif
1197650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter
1198650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter	return true;
1199650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter}
1200650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter
12012c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilsonstatic int i915_load_gem_init(struct drm_device *dev)
120279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{
120379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
120453984635a659e360f206a81ada4ae813152d72f1Daniel Vetter	unsigned long prealloc_size, gtt_size, mappable_size;
12052c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	int ret;
120679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1207c64f7ba5f1006d8c20eacafecf98d4d00a6902a0Chris Wilson	prealloc_size = dev_priv->mm.gtt->stolen_size;
120853984635a659e360f206a81ada4ae813152d72f1Daniel Vetter	gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT;
120953984635a659e360f206a81ada4ae813152d72f1Daniel Vetter	mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
121053984635a659e360f206a81ada4ae813152d72f1Daniel Vetter
1211fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	/* Basic memrange allocator for stolen space */
1212fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size);
121379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1214d3ae08109d628d26615d7f7f4d8d53cdd8d71fd0Daniel Vetter	mutex_lock(&dev->struct_mutex);
1215650dc07ec3b0eba8ff21da706d2b1876ada59fc3Daniel Vetter	if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(dev)) {
12161d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		/* PPGTT pdes are stolen from global gtt ptes, so shrink the
12171d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * aperture accordingly when using aliasing ppgtt. */
12181d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE;
12191d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		/* For paranoia keep the guard page in between. */
12201d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		gtt_size -= PAGE_SIZE;
12211d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter
12221d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		i915_gem_do_init(dev, 0, mappable_size, gtt_size);
12231d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter
12241d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		ret = i915_gem_init_aliasing_ppgtt(dev);
1225e02f14cd48a5da0ebaecf88c93dbd54a81e0deadDaniel Vetter		if (ret) {
1226e02f14cd48a5da0ebaecf88c93dbd54a81e0deadDaniel Vetter			mutex_unlock(&dev->struct_mutex);
12271d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter			return ret;
1228e02f14cd48a5da0ebaecf88c93dbd54a81e0deadDaniel Vetter		}
12291d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter	} else {
12301d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		/* Let GEM Manage all of the aperture.
12311d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 *
12321d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * However, leave one page at the end still bound to the scratch
12331d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * page.  There are a number of places where the hardware
12341d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * apparently prefetches past the end of the object, and we've
12351d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * seen multiple hangs with the GPU head pointer stuck in a
12361d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * batchbuffer bound at the last page of the aperture.  One page
12371d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * should be enough to keep any prefetching inside of the
12381d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 * aperture.
12391d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		 */
12401d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE);
12411d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter	}
124279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1243f691e2f4cec334e906f971471b3bf1460c6256d4Daniel Vetter	ret = i915_gem_init_hw(dev);
124411ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	mutex_unlock(&dev->struct_mutex);
12451d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter	if (ret) {
12461d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		i915_gem_cleanup_aliasing_ppgtt(dev);
12472c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson		return ret;
12481d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter	}
124979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12508082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	/* Try to set up FBC with a reasonable compressed buffer size */
12519216d44dc13b5e858253f06d83ceea25a9b72f4fShaohua Li	if (I915_HAS_FBC(dev) && i915_powersave) {
12528082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		int cfb_size;
12538082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
1254fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		/* Leave 1M for line length buffer & misc. */
1255fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson
1256fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		/* Try to get a 32M buffer... */
1257fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		if (prealloc_size > (36*1024*1024))
1258fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson			cfb_size = 32*1024*1024;
12598082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		else /* fall back to 7/8 of the stolen space */
12608082400327d8d2ca54254b593644942bed0edd25Jesse Barnes			cfb_size = prealloc_size * 7 / 8;
12618082400327d8d2ca54254b593644942bed0edd25Jesse Barnes		i915_setup_compression(dev, cfb_size);
12628082400327d8d2ca54254b593644942bed0edd25Jesse Barnes	}
12638082400327d8d2ca54254b593644942bed0edd25Jesse Barnes
1264fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	/* Allow hardware batchbuffers unless told otherwise. */
126579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev_priv->allow_batchbuffer = 1;
12662c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	return 0;
12672c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson}
12682c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson
12692c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilsonstatic int i915_load_modeset_init(struct drm_device *dev)
12702c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson{
12712c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	struct drm_i915_private *dev_priv = dev->dev_private;
12722c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	int ret;
127379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
12746d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	ret = intel_parse_bios(dev);
127579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
127679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		DRM_INFO("failed to find VBIOS tables\n");
127779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
1278934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	/* If we have > 1 VGA cards, then we need to arbitrate access
1279934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	 * to the common VGA resources.
1280934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	 *
1281934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	 * If we are a secondary display controller (!PCI_DISPLAY_CLASS_VGA),
1282934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	 * then we do not take part in VGA arbitration and the
1283934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	 * vga_client_register() fails with -ENODEV.
1284934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	 */
128528d520433b6375740990ab99d69b0d0067fd656bDave Airlie	ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode);
1286934f992c763ae1e5eefcce8af769c16444085df7Chris Wilson	if (ret && ret != -ENODEV)
12872c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson		goto out;
128828d520433b6375740990ab99d69b0d0067fd656bDave Airlie
1289723bfd707a97fee06eb3ba4d3e8b4714c29a1064Jesse Barnes	intel_register_dsm_handler();
1290723bfd707a97fee06eb3ba4d3e8b4714c29a1064Jesse Barnes
12916a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	ret = vga_switcheroo_register_client(dev->pdev,
12926a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie					     i915_switcheroo_set_state,
12938d608aa6295242fe4c4b6105b8c59c6a5b232d89Dave Airlie					     NULL,
12946a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie					     i915_switcheroo_can_switch);
12956a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie	if (ret)
12965a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson		goto cleanup_vga_client;
12976a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie
12981afe3e9d4335bf3bc5615e37243dc8fef65dac8fJesse Barnes	/* IIR "flip pending" bit means done if this bit is set */
12991afe3e9d4335bf3bc5615e37243dc8fef65dac8fJesse Barnes	if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE))
13001afe3e9d4335bf3bc5615e37243dc8fef65dac8fJesse Barnes		dev_priv->flip_pending_is_done = true;
13011afe3e9d4335bf3bc5615e37243dc8fef65dac8fJesse Barnes
1302b01f2c3a4a37d09a47ad73ccbb46d554d21cfeb0Jesse Barnes	intel_modeset_init(dev);
1303b01f2c3a4a37d09a47ad73ccbb46d554d21cfeb0Jesse Barnes
13042c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	ret = i915_load_gem_init(dev);
130579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (ret)
13065a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson		goto cleanup_vga_switcheroo;
130779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
13082c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	intel_modeset_gem_init(dev);
13092c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson
13102c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	ret = drm_irq_install(dev);
13112c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	if (ret)
13122c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson		goto cleanup_gem;
13132c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson
131479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* Always safe in the mode setting case. */
131579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	/* FIXME: do pre/post-mode set stuff in core KMS code */
131679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	dev->vblank_disable_allowed = 1;
131779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
13185a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson	ret = intel_fbdev_init(dev);
13195a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson	if (ret)
13205a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson		goto cleanup_irq;
13215a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson
1322eb1f8e4f3be898df808e2dfc131099f5831d491dDave Airlie	drm_kms_helper_poll_init(dev);
132387acb0a550694ff1a7725ea3a73b80d8ccf56180Chris Wilson
132487acb0a550694ff1a7725ea3a73b80d8ccf56180Chris Wilson	/* We're off and running w/KMS */
132587acb0a550694ff1a7725ea3a73b80d8ccf56180Chris Wilson	dev_priv->mm.suspended = 0;
132687acb0a550694ff1a7725ea3a73b80d8ccf56180Chris Wilson
132779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
132879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
13295a79395b2791cc70442ab8434aed1b5206683e7cChris Wilsoncleanup_irq:
13305a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson	drm_irq_uninstall(dev);
13312c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilsoncleanup_gem:
13322c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	mutex_lock(&dev->struct_mutex);
13332c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	i915_gem_cleanup_ringbuffer(dev);
13342c7111dbaec72b01c804afb8ad77c6c7523986fdChris Wilson	mutex_unlock(&dev->struct_mutex);
13351d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter	i915_gem_cleanup_aliasing_ppgtt(dev);
13365a79395b2791cc70442ab8434aed1b5206683e7cChris Wilsoncleanup_vga_switcheroo:
13375a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson	vga_switcheroo_unregister_client(dev->pdev);
13385a79395b2791cc70442ab8434aed1b5206683e7cChris Wilsoncleanup_vga_client:
13395a79395b2791cc70442ab8434aed1b5206683e7cChris Wilson	vga_client_register(dev->pdev, NULL, NULL, NULL);
134079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout:
134179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return ret;
134279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes}
134379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
13447c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint i915_master_create(struct drm_device *dev, struct drm_master *master)
13457c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
13467c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv;
13477c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13489a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL);
13497c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv)
13507c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return -ENOMEM;
13517c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13527c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->driver_priv = master_priv;
13537c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	return 0;
13547c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
13557c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13567c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid i915_master_destroy(struct drm_device *dev, struct drm_master *master)
13577c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{
13587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	struct drm_i915_master_private *master_priv = master->driver_priv;
13597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	if (!master_priv)
13617c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie		return;
13627c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13639a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(master_priv);
13647c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13657c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie	master->driver_priv = NULL;
13667c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie}
13677c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie
13687648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesstatic void i915_pineview_get_mem_freq(struct drm_device *dev)
13697662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li{
13707662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	drm_i915_private_t *dev_priv = dev->dev_private;
13717662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	u32 tmp;
13727662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13737662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	tmp = I915_READ(CLKCFG);
13747662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13757662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	switch (tmp & CLKCFG_FSB_MASK) {
13767662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_533:
13777662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq = 533; /* 133*4 */
13787662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13797662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_800:
13807662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq = 800; /* 200*4 */
13817662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13827662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_667:
13837662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq =  667; /* 167*4 */
13847662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13857662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_FSB_400:
13867662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->fsb_freq = 400; /* 100*4 */
13877662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13887662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	}
13897662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
13907662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	switch (tmp & CLKCFG_MEM_MASK) {
13917662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_MEM_533:
13927662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->mem_freq = 533;
13937662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13947662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_MEM_667:
13957662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->mem_freq = 667;
13967662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
13977662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	case CLKCFG_MEM_800:
13987662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		dev_priv->mem_freq = 800;
13997662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li		break;
14007662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li	}
14019553426372eef71c849499fb1d232f4b0577c0f9Li Peng
14029553426372eef71c849499fb1d232f4b0577c0f9Li Peng	/* detect pineview DDR3 setting */
14039553426372eef71c849499fb1d232f4b0577c0f9Li Peng	tmp = I915_READ(CSHRDDR3CTL);
14049553426372eef71c849499fb1d232f4b0577c0f9Li Peng	dev_priv->is_ddr3 = (tmp & CSHRDDR3CTL_DDR3) ? 1 : 0;
14057662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li}
14067662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
14077648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesstatic void i915_ironlake_get_mem_freq(struct drm_device *dev)
14087648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
14097648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
14107648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u16 ddrpll, csipll;
14117648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14127648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	ddrpll = I915_READ16(DDRMPLL1);
14137648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	csipll = I915_READ16(CSIPLL0);
14147648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14157648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	switch (ddrpll & 0xff) {
14167648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0xc:
14177648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->mem_freq = 800;
14187648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14197648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x10:
14207648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->mem_freq = 1066;
14217648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14227648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x14:
14237648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->mem_freq = 1333;
14247648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14257648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x18:
14267648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->mem_freq = 1600;
14277648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14287648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	default:
14297648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		DRM_DEBUG_DRIVER("unknown memory frequency 0x%02x\n",
14307648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes				 ddrpll & 0xff);
14317648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->mem_freq = 0;
14327648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14337648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
14347648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14357648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->r_t = dev_priv->mem_freq;
14367648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14377648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	switch (csipll & 0x3ff) {
14387648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x00c:
14397648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 3200;
14407648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14417648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x00e:
14427648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 3733;
14437648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14447648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x010:
14457648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 4266;
14467648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14477648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x012:
14487648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 4800;
14497648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14507648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x014:
14517648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 5333;
14527648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14537648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x016:
14547648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 5866;
14557648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14567648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	case 0x018:
14577648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 6400;
14587648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14597648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	default:
14607648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		DRM_DEBUG_DRIVER("unknown fsb frequency 0x%04x\n",
14617648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes				 csipll & 0x3ff);
14627648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->fsb_freq = 0;
14637648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		break;
14647648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
14657648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14667648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (dev_priv->fsb_freq == 3200) {
14677648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->c_m = 0;
14687648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	} else if (dev_priv->fsb_freq > 3200 && dev_priv->fsb_freq <= 4800) {
14697648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->c_m = 1;
14707648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	} else {
14717648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->c_m = 2;
14727648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
14737648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
14747648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
1475faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilsonstatic const struct cparams {
1476faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	u16 i;
1477faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	u16 t;
1478faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	u16 m;
1479faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	u16 c;
1480faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson} cparams[] = {
14817648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	{ 1, 1333, 301, 28664 },
14827648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	{ 1, 1066, 294, 24460 },
14837648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	{ 1, 800, 294, 25192 },
14847648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	{ 0, 1333, 276, 27605 },
14857648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	{ 0, 1066, 276, 27605 },
14867648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	{ 0, 800, 231, 23784 },
14877648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes};
14887648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14897648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesunsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
14907648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
14917648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u64 total_count, diff, ret;
14927648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u32 count1, count2, count3, m = 0, c = 0;
14937648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	unsigned long now = jiffies_to_msecs(jiffies), diff1;
14947648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	int i;
14957648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14967648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	diff1 = now - dev_priv->last_time1;
14977648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
14984ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	/* Prevent division-by-zero if we are asking too fast.
14994ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	 * Also, we don't get interesting results if we are polling
15004ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	 * faster than once in 10ms, so just return the saved value
15014ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	 * in such cases.
15024ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	 */
15034ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	if (diff1 <= 10)
15044ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov		return dev_priv->chipset_power;
15054ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov
15067648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	count1 = I915_READ(DMIEC);
15077648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	count2 = I915_READ(DDREC);
15087648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	count3 = I915_READ(CSIEC);
15097648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15107648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	total_count = count1 + count2 + count3;
15117648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15127648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	/* FIXME: handle per-counter overflow */
15137648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (total_count < dev_priv->last_count1) {
15147648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		diff = ~0UL - dev_priv->last_count1;
15157648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		diff += total_count;
15167648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	} else {
15177648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		diff = total_count - dev_priv->last_count1;
15187648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
15197648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15207648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	for (i = 0; i < ARRAY_SIZE(cparams); i++) {
15217648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		if (cparams[i].i == dev_priv->c_m &&
15227648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		    cparams[i].t == dev_priv->r_t) {
15237648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes			m = cparams[i].m;
15247648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes			c = cparams[i].c;
15257648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes			break;
15267648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		}
15277648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
15287648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
1529d270ae34eb77c58dea60e5b1e300a698d2ce39acJesse Barnes	diff = div_u64(diff, diff1);
15307648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	ret = ((m * diff) + c);
1531d270ae34eb77c58dea60e5b1e300a698d2ce39acJesse Barnes	ret = div_u64(ret, 10);
15327648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15337648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->last_count1 = total_count;
15347648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->last_time1 = now;
15357648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15364ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov	dev_priv->chipset_power = ret;
15374ed0b577457eb6aeb7cdc7e7316576e63d15abb2Eugeni Dodonov
15387648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	return ret;
15397648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
15407648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15417648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesunsigned long i915_mch_val(struct drm_i915_private *dev_priv)
15427648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
15437648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	unsigned long m, x, b;
15447648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u32 tsfs;
15457648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15467648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	tsfs = I915_READ(TSFS);
15477648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15487648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	m = ((tsfs & TSFS_SLOPE_MASK) >> TSFS_SLOPE_SHIFT);
15497648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	x = I915_READ8(TR1);
15507648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15517648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	b = tsfs & TSFS_INTR_MASK;
15527648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
15537648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	return ((m * x) / 127) - b;
15547648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
15557648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
1556faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilsonstatic u16 pvid_to_extvid(struct drm_i915_private *dev_priv, u8 pxvid)
15577648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
1558faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	static const struct v_table {
1559faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		u16 vd; /* in .1 mil */
1560faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		u16 vm; /* in .1 mil */
1561faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	} v_table[] = {
1562faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 0, 0, },
1563faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 375, 0, },
1564faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 500, 0, },
1565faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 625, 0, },
1566faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 750, 0, },
1567faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 875, 0, },
1568faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 1000, 0, },
1569faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 1125, 0, },
1570faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1571faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1572faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1573faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1574faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1575faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1576faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1577faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1578faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1579faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1580faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1581faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1582faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1583faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1584faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1585faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1586faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1587faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1588faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1589faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1590faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1591faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1592faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1593faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4125, 3000, },
1594faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4250, 3125, },
1595faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4375, 3250, },
1596faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4500, 3375, },
1597faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4625, 3500, },
1598faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4750, 3625, },
1599faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 4875, 3750, },
1600faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5000, 3875, },
1601faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5125, 4000, },
1602faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5250, 4125, },
1603faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5375, 4250, },
1604faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5500, 4375, },
1605faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5625, 4500, },
1606faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5750, 4625, },
1607faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 5875, 4750, },
1608faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6000, 4875, },
1609faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6125, 5000, },
1610faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6250, 5125, },
1611faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6375, 5250, },
1612faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6500, 5375, },
1613faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6625, 5500, },
1614faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6750, 5625, },
1615faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 6875, 5750, },
1616faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7000, 5875, },
1617faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7125, 6000, },
1618faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7250, 6125, },
1619faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7375, 6250, },
1620faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7500, 6375, },
1621faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7625, 6500, },
1622faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7750, 6625, },
1623faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 7875, 6750, },
1624faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8000, 6875, },
1625faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8125, 7000, },
1626faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8250, 7125, },
1627faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8375, 7250, },
1628faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8500, 7375, },
1629faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8625, 7500, },
1630faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8750, 7625, },
1631faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 8875, 7750, },
1632faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9000, 7875, },
1633faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9125, 8000, },
1634faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9250, 8125, },
1635faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9375, 8250, },
1636faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9500, 8375, },
1637faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9625, 8500, },
1638faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9750, 8625, },
1639faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 9875, 8750, },
1640faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10000, 8875, },
1641faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10125, 9000, },
1642faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10250, 9125, },
1643faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10375, 9250, },
1644faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10500, 9375, },
1645faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10625, 9500, },
1646faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10750, 9625, },
1647faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 10875, 9750, },
1648faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11000, 9875, },
1649faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11125, 10000, },
1650faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11250, 10125, },
1651faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11375, 10250, },
1652faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11500, 10375, },
1653faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11625, 10500, },
1654faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11750, 10625, },
1655faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 11875, 10750, },
1656faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12000, 10875, },
1657faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12125, 11000, },
1658faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12250, 11125, },
1659faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12375, 11250, },
1660faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12500, 11375, },
1661faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12625, 11500, },
1662faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12750, 11625, },
1663faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 12875, 11750, },
1664faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13000, 11875, },
1665faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13125, 12000, },
1666faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13250, 12125, },
1667faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13375, 12250, },
1668faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13500, 12375, },
1669faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13625, 12500, },
1670faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13750, 12625, },
1671faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 13875, 12750, },
1672faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14000, 12875, },
1673faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14125, 13000, },
1674faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14250, 13125, },
1675faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14375, 13250, },
1676faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14500, 13375, },
1677faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14625, 13500, },
1678faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14750, 13625, },
1679faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 14875, 13750, },
1680faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15000, 13875, },
1681faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15125, 14000, },
1682faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15250, 14125, },
1683faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15375, 14250, },
1684faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15500, 14375, },
1685faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15625, 14500, },
1686faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15750, 14625, },
1687faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 15875, 14750, },
1688faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 16000, 14875, },
1689faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		{ 16125, 15000, },
1690faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	};
1691faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	if (dev_priv->info->is_mobile)
1692faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		return v_table[pxvid].vm;
1693faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson	else
1694faa60c4174d943696b9478c5de6438c4f0fecba6Chris Wilson		return v_table[pxvid].vd;
16957648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
16967648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
16977648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesvoid i915_update_gfx_val(struct drm_i915_private *dev_priv)
16987648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
16997648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	struct timespec now, diff1;
17007648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u64 diff;
17017648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	unsigned long diffms;
17027648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u32 count;
17037648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
1704e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson	if (dev_priv->info->gen != 5)
1705e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson		return;
1706e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson
17077648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	getrawmonotonic(&now);
17087648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	diff1 = timespec_sub(now, dev_priv->last_time2);
17097648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17107648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	/* Don't divide by 0 */
17117648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	diffms = diff1.tv_sec * 1000 + diff1.tv_nsec / 1000000;
17127648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!diffms)
17137648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		return;
17147648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17157648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	count = I915_READ(GFXEC);
17167648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17177648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (count < dev_priv->last_count2) {
17187648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		diff = ~0UL - dev_priv->last_count2;
17197648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		diff += count;
17207648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	} else {
17217648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		diff = count - dev_priv->last_count2;
17227648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
17237648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17247648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->last_count2 = count;
17257648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->last_time2 = now;
17267648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17277648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	/* More magic constants... */
17287648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	diff = diff * 1181;
1729d270ae34eb77c58dea60e5b1e300a698d2ce39acJesse Barnes	diff = div_u64(diff, diffms * 10);
17307648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->gfx_power = diff;
17317648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
17327648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17337648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesunsigned long i915_gfx_val(struct drm_i915_private *dev_priv)
17347648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
17357648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	unsigned long t, corr, state1, corr2, state2;
17367648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	u32 pxvid, ext_v;
17377648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17387648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	pxvid = I915_READ(PXVFREQ_BASE + (dev_priv->cur_delay * 4));
17397648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	pxvid = (pxvid >> 24) & 0x7f;
17407648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	ext_v = pvid_to_extvid(dev_priv, pxvid);
17417648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17427648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	state1 = ext_v;
17437648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17447648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	t = i915_mch_val(dev_priv);
17457648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17467648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	/* Revel in the empirically derived constants */
17477648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17487648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	/* Correction factor in 1/100000 units */
17497648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (t > 80)
17507648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		corr = ((t * 2349) + 135940);
17517648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	else if (t >= 50)
17527648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		corr = ((t * 964) + 29317);
17537648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	else /* < 50 */
17547648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		corr = ((t * 301) + 1004);
17557648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17567648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	corr = corr * ((150142 * state1) / 10000 - 78642);
17577648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	corr /= 100000;
17587648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	corr2 = (corr * dev_priv->corr);
17597648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17607648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	state2 = (corr2 * state1) / 10000;
17617648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	state2 /= 100; /* convert to mW */
17627648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17637648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	i915_update_gfx_val(dev_priv);
17647648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17657648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	return dev_priv->gfx_power + state2;
17667648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
17677648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17687648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/* Global for IPS driver to get at the current i915 device */
17697648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesstatic struct drm_i915_private *i915_mch_dev;
17707648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/*
17717648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * Lock protecting IPS related data structures
17727648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *   - i915_mch_dev
17737648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *   - dev_priv->max_delay
17747648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *   - dev_priv->min_delay
17757648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *   - dev_priv->fmax
17767648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *   - dev_priv->gpu_busy
17777648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes */
1778995b6762f0fd54377bbfafdf5328b12de698bfa8Chris Wilsonstatic DEFINE_SPINLOCK(mchdev_lock);
17797648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17807648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/**
17817648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * i915_read_mch_val - return value for IPS use
17827648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *
17837648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * Calculate and return a value for the IPS driver to use when deciding whether
17847648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * we have thermal and power headroom to increase CPU or GPU power budget.
17857648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes */
17867648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesunsigned long i915_read_mch_val(void)
17877648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
17880206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	struct drm_i915_private *dev_priv;
17897648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	unsigned long chipset_val, graphics_val, ret = 0;
17907648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17910206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_lock(&mchdev_lock);
17927648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!i915_mch_dev)
17937648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		goto out_unlock;
17947648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv = i915_mch_dev;
17957648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17967648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	chipset_val = i915_chipset_val(dev_priv);
17977648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	graphics_val = i915_gfx_val(dev_priv);
17987648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
17997648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	ret = chipset_val + graphics_val;
18007648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18017648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesout_unlock:
18020206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_unlock(&mchdev_lock);
18037648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18040206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	return ret;
18057648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
18067648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse BarnesEXPORT_SYMBOL_GPL(i915_read_mch_val);
18077648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18087648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/**
18097648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * i915_gpu_raise - raise GPU frequency limit
18107648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *
18117648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * Raise the limit; IPS indicates we have thermal headroom.
18127648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes */
18137648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesbool i915_gpu_raise(void)
18147648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
18150206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	struct drm_i915_private *dev_priv;
18167648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	bool ret = true;
18177648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18180206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_lock(&mchdev_lock);
18197648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!i915_mch_dev) {
18207648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		ret = false;
18217648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		goto out_unlock;
18227648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
18237648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv = i915_mch_dev;
18247648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18257648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (dev_priv->max_delay > dev_priv->fmax)
18267648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->max_delay--;
18277648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18287648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesout_unlock:
18290206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_unlock(&mchdev_lock);
18307648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18310206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	return ret;
18327648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
18337648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse BarnesEXPORT_SYMBOL_GPL(i915_gpu_raise);
18347648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18357648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/**
18367648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * i915_gpu_lower - lower GPU frequency limit
18377648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *
18387648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * IPS indicates we're close to a thermal limit, so throttle back the GPU
18397648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * frequency maximum.
18407648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes */
18417648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesbool i915_gpu_lower(void)
18427648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
18430206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	struct drm_i915_private *dev_priv;
18447648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	bool ret = true;
18457648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18460206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_lock(&mchdev_lock);
18477648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!i915_mch_dev) {
18487648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		ret = false;
18497648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		goto out_unlock;
18507648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
18517648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv = i915_mch_dev;
18527648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18537648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (dev_priv->max_delay < dev_priv->min_delay)
18547648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		dev_priv->max_delay++;
18557648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18567648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesout_unlock:
18570206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_unlock(&mchdev_lock);
18587648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18590206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	return ret;
18607648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
18617648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse BarnesEXPORT_SYMBOL_GPL(i915_gpu_lower);
18627648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18637648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/**
18647648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * i915_gpu_busy - indicate GPU business to IPS
18657648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *
18667648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * Tell the IPS driver whether or not the GPU is busy.
18677648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes */
18687648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesbool i915_gpu_busy(void)
18697648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
18700206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	struct drm_i915_private *dev_priv;
18717648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	bool ret = false;
18727648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18730206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_lock(&mchdev_lock);
18747648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!i915_mch_dev)
18757648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		goto out_unlock;
18767648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv = i915_mch_dev;
18777648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18787648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	ret = dev_priv->busy;
18797648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18807648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesout_unlock:
18810206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_unlock(&mchdev_lock);
18827648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18830206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	return ret;
18847648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
18857648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse BarnesEXPORT_SYMBOL_GPL(i915_gpu_busy);
18867648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18877648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes/**
18887648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * i915_gpu_turbo_disable - disable graphics turbo
18897648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes *
18907648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * Disable graphics turbo by resetting the max frequency and setting the
18917648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes * current frequency to the default.
18927648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes */
18937648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesbool i915_gpu_turbo_disable(void)
18947648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes{
18950206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	struct drm_i915_private *dev_priv;
18967648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	bool ret = true;
18977648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
18980206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_lock(&mchdev_lock);
18997648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!i915_mch_dev) {
19007648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		ret = false;
19017648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		goto out_unlock;
19027648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	}
19037648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv = i915_mch_dev;
19047648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
19057648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	dev_priv->max_delay = dev_priv->fstart;
19067648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
19077648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (!ironlake_set_drps(dev_priv->dev, dev_priv->fstart))
19087648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		ret = false;
19097648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
19107648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnesout_unlock:
19110206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	spin_unlock(&mchdev_lock);
19127648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
19130206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	return ret;
19147648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes}
19157648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse BarnesEXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
19167648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
191779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
191863ee41d794d9c555f84205517a68509848988760Eric Anholt * Tells the intel_ips driver that the i915 driver is now loaded, if
191963ee41d794d9c555f84205517a68509848988760Eric Anholt * IPS got loaded first.
192063ee41d794d9c555f84205517a68509848988760Eric Anholt *
192163ee41d794d9c555f84205517a68509848988760Eric Anholt * This awkward dance is so that neither module has to depend on the
192263ee41d794d9c555f84205517a68509848988760Eric Anholt * other in order for IPS to do the appropriate communication of
192363ee41d794d9c555f84205517a68509848988760Eric Anholt * GPU turbo limits to i915.
192463ee41d794d9c555f84205517a68509848988760Eric Anholt */
192563ee41d794d9c555f84205517a68509848988760Eric Anholtstatic void
192663ee41d794d9c555f84205517a68509848988760Eric Anholtips_ping_for_i915_load(void)
192763ee41d794d9c555f84205517a68509848988760Eric Anholt{
192863ee41d794d9c555f84205517a68509848988760Eric Anholt	void (*link)(void);
192963ee41d794d9c555f84205517a68509848988760Eric Anholt
193063ee41d794d9c555f84205517a68509848988760Eric Anholt	link = symbol_get(ips_link_to_i915_driver);
193163ee41d794d9c555f84205517a68509848988760Eric Anholt	if (link) {
193263ee41d794d9c555f84205517a68509848988760Eric Anholt		link();
193363ee41d794d9c555f84205517a68509848988760Eric Anholt		symbol_put(ips_link_to_i915_driver);
193463ee41d794d9c555f84205517a68509848988760Eric Anholt	}
193563ee41d794d9c555f84205517a68509848988760Eric Anholt}
193663ee41d794d9c555f84205517a68509848988760Eric Anholt
193763ee41d794d9c555f84205517a68509848988760Eric Anholt/**
193879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_load - setup chip and create an initial config
193979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
194079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @flags: startup flags
194179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
194279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * The driver load routine has to do several things:
194379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - drive output discovery via intel_modeset_init()
194479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - initialize the memory manager
194579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - allocate initial config memory
194679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *   - setup the DRM framebuffer with the allocated memory
194779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
194884b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags)
194922eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{
1950ea059a1ec4496a10f94ca9d0c1b530faf1b85dceLuca Tettamanti	struct drm_i915_private *dev_priv;
1951cfdf1fa23f4074c9f8766dc67a928bbf680b1ac9Kristian Høgsberg	int ret = 0, mmio_bar;
1952fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson	uint32_t agp_size;
1953fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson
195422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	/* i915 has 4 more counters */
195522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->counters += 4;
195622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[6] = _DRM_STAT_IRQ;
195722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[7] = _DRM_STAT_PRIMARY;
195822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[8] = _DRM_STAT_SECONDARY;
195922eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	dev->types[9] = _DRM_STAT_DMA;
196022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
19619a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL);
1962ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	if (dev_priv == NULL)
1963ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes		return -ENOMEM;
1964ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1965ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	dev->dev_private = (void *)dev_priv;
1966673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	dev_priv->dev = dev;
1967cfdf1fa23f4074c9f8766dc67a928bbf680b1ac9Kristian Høgsberg	dev_priv->info = (struct intel_device_info *) flags;
1968ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
1969ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	if (i915_get_bridge_dev(dev)) {
1970ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		ret = -EIO;
1971ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie		goto free_priv;
1972ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	}
1973ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie
1974466e69b8b03b8c1987367912782bc12988ad8794Dave Airlie	pci_set_master(dev->pdev);
1975466e69b8b03b8c1987367912782bc12988ad8794Dave Airlie
19769f82d23846146990d475f6753be733e55788d88dDaniel Vetter	/* overlay on gen2 is broken and can't address above 1G */
19779f82d23846146990d475f6753be733e55788d88dDaniel Vetter	if (IS_GEN2(dev))
19789f82d23846146990d475f6753be733e55788d88dDaniel Vetter		dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(30));
19799f82d23846146990d475f6753be733e55788d88dDaniel Vetter
19806927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	/* 965GM sometimes incorrectly writes to hardware status page (HWS)
19816927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 * using 32bit addressing, overwriting memory if HWS is located
19826927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 * above 4GB.
19836927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 *
19846927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 * The documentation also mentions an issue with undefined
19856927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 * behaviour if any general state is accessed within a page above 4GB,
19866927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 * which also needs to be handled carefully.
19876927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	 */
19886927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann	if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
19896927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann		dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
19906927faf30920b8c03dfa007e732642a1f1f20089Jan Niehusmann
1991b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson	mmio_bar = IS_GEN2(dev) ? 1 : 0;
1992b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson	dev_priv->regs = pci_iomap(dev->pdev, mmio_bar, 0);
1993b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson	if (!dev_priv->regs) {
1994b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson		DRM_ERROR("failed to map registers\n");
1995b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson		ret = -EIO;
1996b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson		goto put_bridge;
1997b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson	}
1998b4ce0f85159f77f208a62930f67b4e548576a5a3Chris Wilson
199971e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson	dev_priv->mm.gtt = intel_gtt_get();
200071e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson	if (!dev_priv->mm.gtt) {
200171e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson		DRM_ERROR("Failed to initialize GTT\n");
200271e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson		ret = -ENODEV;
2003a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard		goto out_rmmap;
200471e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson	}
200571e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson
200671e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;
200771e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson
20080206e353a0416ad63ce07f53c807c2c725633b87Akshay Joshi	dev_priv->mm.gtt_mapping =
200971e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson		io_mapping_create_wc(dev->agp->base, agp_size);
20106644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	if (dev_priv->mm.gtt_mapping == NULL) {
20116644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi		ret = -EIO;
20126644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi		goto out_rmmap;
20136644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	}
20146644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi
2015ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	/* Set up a WC MTRR for non-PAT systems.  This is more common than
2016ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * one would think, because the kernel disables PAT on first
2017ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * generation Core chips because WC PAT gets overridden by a UC
2018ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 * MTRR if present.  Even if a UC MTRR isn't present.
2019ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	 */
2020ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base,
202171e9339c3389de6a685ecb26261a81b8a583aa1cChris Wilson					 agp_size,
2022ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt					 MTRR_TYPE_WRCOMB, 1);
2023ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	if (dev_priv->mm.gtt_mtrr < 0) {
2024040aefa263aa9cd7bd5df50586c35e1e15e77f84Eric Anholt		DRM_INFO("MTRR allocation failed.  Graphics "
2025ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt			 "performance may suffer.\n");
2026ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	}
202719966754328d99ee003ddfc7a8c31ceb115483acDaniel Vetter
2028e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	/* The i915 workqueue is primarily used for batched retirement of
2029e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * requests (and thus managing bo) once the task has been completed
2030e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * by the GPU. i915_gem_retire_requests() is called directly when we
2031e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * need high-priority retirement, such as waiting for an explicit
2032e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * bo.
2033e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 *
2034e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * It is also used for periodic low-priority events, such as
2035df9c2042858e85ab46731c13e708a5b0799db848Eric Anholt	 * idle-timers and recording error state.
2036e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 *
2037e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * All tasks on the workqueue are expected to acquire the dev mutex
2038e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * so there is no point in running more than one instance of the
2039e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 * workqueue at any time: max_active = 1 and NON_REENTRANT.
2040e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	 */
2041e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson	dev_priv->wq = alloc_workqueue("i915",
2042e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson				       WQ_UNBOUND | WQ_NON_REENTRANT,
2043e642abbf303741b245375b2e3f8f00e900d462dcChris Wilson				       1);
20449c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	if (dev_priv->wq == NULL) {
20459c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt		DRM_ERROR("Failed to create our workqueue.\n");
20469c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt		ret = -ENOMEM;
2047a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard		goto out_mtrrfree;
20489c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	}
20499c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt
2050ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	/* enable GEM by default */
2051ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie	dev_priv->has_gem = 1;
2052ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie
2053f71d4af4cd475aced6d9ec9730b03885ac80b833Jesse Barnes	intel_irq_init(dev);
20549880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes
2055c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	/* Try to make sure MCHBAR is enabled before poking at it */
2056c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	intel_setup_mchbar(dev);
2057f899fc64cda8569d0529452aafc0da31c042df2eChris Wilson	intel_setup_gmbus(dev);
205844834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	intel_opregion_setup(dev);
2059c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
20606d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	/* Make sure the bios did its job and set up vital registers */
20616d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed	intel_setup_bios(dev);
20626d139a87b747aaebc969ac5f4eb8db766fcd9cbdBryan Freed
2063673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_load(dev);
2064673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
2065398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	/* Init HWS */
2066398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	if (!I915_NEED_GFX_HWS(dev)) {
2067398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard		ret = i915_init_phys_hws(dev);
206856e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson		if (ret)
206956e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson			goto out_gem_unload;
2070398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard	}
2071ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
20727648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	if (IS_PINEVIEW(dev))
20737648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		i915_pineview_get_mem_freq(dev);
2074f00a3ddf91d596bece5fa31e8ce2e8a3b4c0623bChris Wilson	else if (IS_GEN5(dev))
20757648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes		i915_ironlake_get_mem_freq(dev);
20767662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li
2077ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	/* On the 945G/GM, the chipset reports the MSI capability on the
2078ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * integrated graphics even though the support isn't actually there
2079ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * according to the published specs.  It doesn't appear to function
2080ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * correctly in testing on 945G.
2081ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * This may be a side effect of MSI having been made available for PEG
2082ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 * and the registers being closely associated.
2083d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard	 *
2084d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard	 * According to chipset errata, on the 965GM, MSI interrupts may
2085b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	 * be lost or delayed, but we use them anyways to avoid
2086b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	 * stuck interrupts on some machines.
2087ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	 */
2088b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard	if (!IS_I945G(dev) && !IS_I945GM(dev))
2089d3e74d0237b102d34979015fbf6df02ca4413074Eric Anholt		pci_enable_msi(dev->pdev);
2090ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
20919f1f46a45a681d357d1ceedecec3671a5ae957f4Daniel Vetter	spin_lock_init(&dev_priv->gt_lock);
20921ec14ad3132702694f2e1a90b30641cf111183b9Chris Wilson	spin_lock_init(&dev_priv->irq_lock);
209363eeaf38251183ec2b1caee11e4a2c040cb5ce6cJesse Barnes	spin_lock_init(&dev_priv->error_lock);
20944912d04193733a825216b926ffd290fada88ab07Ben Widawsky	spin_lock_init(&dev_priv->rps_lock);
2095ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
209627f8227b1e2b326a9a0995dd9c1f14893c61ee01Jesse Barnes	if (IS_IVYBRIDGE(dev))
209727f8227b1e2b326a9a0995dd9c1f14893c61ee01Jesse Barnes		dev_priv->num_pipe = 3;
209827f8227b1e2b326a9a0995dd9c1f14893c61ee01Jesse Barnes	else if (IS_MOBILE(dev) || !IS_GEN2(dev))
20999db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes		dev_priv->num_pipe = 2;
21009db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes	else
21019db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes		dev_priv->num_pipe = 1;
21029db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes
21039db4a9c7b2a3bd5b4952846bc0c2f58daa80ddd7Jesse Barnes	ret = drm_vblank_init(dev, dev_priv->num_pipe);
210456e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson	if (ret)
210556e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson		goto out_gem_unload;
210652440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard
210711ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	/* Start out suspended */
210811ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari	dev_priv->mm.suspended = 1;
210911ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari
21103bad0781832e4e8c9a532f1169bfcd7257bcfd9eZhenyu Wang	intel_detect_pch(dev);
21113bad0781832e4e8c9a532f1169bfcd7257bcfd9eZhenyu Wang
211279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
211353984635a659e360f206a81ada4ae813152d72f1Daniel Vetter		ret = i915_load_modeset_init(dev);
211479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		if (ret < 0) {
211579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes			DRM_ERROR("failed to init modeset\n");
211656e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson			goto out_gem_unload;
211779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		}
211879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
211979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
212074a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett	/* Must be done after probing outputs */
212144834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	intel_opregion_init(dev);
212244834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	acpi_video_register();
212374a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett
2124f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari	setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed,
2125f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari		    (unsigned long) dev);
21267648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
2127e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson	if (IS_GEN5(dev)) {
2128e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson		spin_lock(&mchdev_lock);
2129e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson		i915_mch_dev = dev_priv;
2130e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson		dev_priv->mchdev_lock = &mchdev_lock;
2131e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson		spin_unlock(&mchdev_lock);
21327648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
2133e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson		ips_ping_for_i915_load();
2134e90f3b61f4432e3c5bb6b57f4b3e8d8cba747541Chris Wilson	}
213563ee41d794d9c555f84205517a68509848988760Eric Anholt
213679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	return 0;
213779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
213856e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilsonout_gem_unload:
2139a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard	if (dev_priv->mm.inactive_shrinker.shrink)
2140a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard		unregister_shrinker(&dev_priv->mm.inactive_shrinker);
2141a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard
214256e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson	if (dev->pdev->msi_enabled)
214356e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson		pci_disable_msi(dev->pdev);
214456e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson
214556e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson	intel_teardown_gmbus(dev);
214656e2ea346ab4c2ea159ecdec85fffc24f50c2903Chris Wilson	intel_teardown_mchbar(dev);
21479c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt	destroy_workqueue(dev_priv->wq);
2148a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packardout_mtrrfree:
2149a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard	if (dev_priv->mm.gtt_mtrr >= 0) {
2150a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard		mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
2151a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard			 dev->agp->agp_info.aper_size * 1024 * 1024);
2152a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard		dev_priv->mm.gtt_mtrr = -1;
2153a7b85d2aa63ed09cd5a4a640772b3272f5ac7caaKeith Packard	}
21546644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi	io_mapping_free(dev_priv->mm.gtt_mapping);
215579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout_rmmap:
21566dda569fe0fb71a03e2a2e815761796f98232cdbChris Wilson	pci_iounmap(dev->pdev, dev_priv->regs);
2157ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlieput_bridge:
2158ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	pci_dev_put(dev_priv->bridge_dev);
215979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesfree_priv:
21609a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev_priv);
2161ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	return ret;
2162ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes}
2163ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
2164ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev)
2165ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{
2166ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	struct drm_i915_private *dev_priv = dev->dev_private;
2167c911fc1c6ad61b56869ee521f1a477c741b039daDaniel Vetter	int ret;
2168ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
21697648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	spin_lock(&mchdev_lock);
21707648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	i915_mch_dev = NULL;
21717648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes	spin_unlock(&mchdev_lock);
21727648fa99eb77a2e1a90b7beaa420e07d819b9c11Jesse Barnes
217317250b71553680bc6e927497aa619ab06ab1015bChris Wilson	if (dev_priv->mm.inactive_shrinker.shrink)
217417250b71553680bc6e927497aa619ab06ab1015bChris Wilson		unregister_shrinker(&dev_priv->mm.inactive_shrinker);
217517250b71553680bc6e927497aa619ab06ab1015bChris Wilson
2176c911fc1c6ad61b56869ee521f1a477c741b039daDaniel Vetter	mutex_lock(&dev->struct_mutex);
2177b93f9cf14e714c20ce9a544ed1a6070ee7604588Ben Widawsky	ret = i915_gpu_idle(dev, true);
2178c911fc1c6ad61b56869ee521f1a477c741b039daDaniel Vetter	if (ret)
2179c911fc1c6ad61b56869ee521f1a477c741b039daDaniel Vetter		DRM_ERROR("failed to idle hardware: %d\n", ret);
2180c911fc1c6ad61b56869ee521f1a477c741b039daDaniel Vetter	mutex_unlock(&dev->struct_mutex);
2181c911fc1c6ad61b56869ee521f1a477c741b039daDaniel Vetter
218275ef9da2cdb64e7926404dd2b755bbbfe98eaeafDaniel Vetter	/* Cancel the retire work handler, which should be idle now. */
218375ef9da2cdb64e7926404dd2b755bbbfe98eaeafDaniel Vetter	cancel_delayed_work_sync(&dev_priv->mm.retire_work);
218475ef9da2cdb64e7926404dd2b755bbbfe98eaeafDaniel Vetter
2185ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	io_mapping_free(dev_priv->mm.gtt_mapping);
2186ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	if (dev_priv->mm.gtt_mtrr >= 0) {
2187ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base,
2188ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt			 dev->agp->agp_info.aper_size * 1024 * 1024);
2189ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt		dev_priv->mm.gtt_mtrr = -1;
2190ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt	}
2191ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt
219244834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	acpi_video_unregister();
219344834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson
219479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
21957b4f3990a22fbe800945f12001bc30db374d0af5Chris Wilson		intel_fbdev_fini(dev);
21963d8620cc5f8538364ee152811e2bd8713abb1d58Jesse Barnes		intel_modeset_cleanup(dev);
21973d8620cc5f8538364ee152811e2bd8713abb1d58Jesse Barnes
21986363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		/*
21996363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		 * free the memory space allocated for the child device
22006363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		 * config parsed from VBT
22016363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		 */
22026363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		if (dev_priv->child_dev && dev_priv->child_dev_num) {
22036363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			kfree(dev_priv->child_dev);
22046363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			dev_priv->child_dev = NULL;
22056363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui			dev_priv->child_dev_num = 0;
22066363ee6f496eb7e3b3f78dc105e522c7b496089bZhao Yakui		}
22076c0d93500eb50098e4e35b8b79e073f2f2f5b773Daniel Vetter
22086a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		vga_switcheroo_unregister_client(dev->pdev);
220928d520433b6375740990ab99d69b0d0067fd656bDave Airlie		vga_client_register(dev->pdev, NULL, NULL, NULL);
221079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
221179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2212a8b4899e4658e53c0c8f4206af105e358e39ee93Daniel Vetter	/* Free error state after interrupts are fully disabled. */
2213bc0c7f14432f7f94b16f972f2d23b8c1248249b4Daniel Vetter	del_timer_sync(&dev_priv->hangcheck_timer);
2214bc0c7f14432f7f94b16f972f2d23b8c1248249b4Daniel Vetter	cancel_work_sync(&dev_priv->error_work);
2215a8b4899e4658e53c0c8f4206af105e358e39ee93Daniel Vetter	i915_destroy_error_state(dev);
2216bc0c7f14432f7f94b16f972f2d23b8c1248249b4Daniel Vetter
2217ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt	if (dev->pdev->msi_enabled)
2218ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt		pci_disable_msi(dev->pdev);
2219ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt
222044834a67c0082e2cf74b16be91e49108b1432d65Chris Wilson	intel_opregion_fini(dev);
22218ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett
222279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
222367e77c5ae8bff6f805d207541f1315051248a87bDaniel Vetter		/* Flush any outstanding unpin_work. */
222467e77c5ae8bff6f805d207541f1315051248a87bDaniel Vetter		flush_workqueue(dev_priv->wq);
222567e77c5ae8bff6f805d207541f1315051248a87bDaniel Vetter
222679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		mutex_lock(&dev->struct_mutex);
2227ecbec53b1d00ba582f71b210ed96cafc05ebd189Hugh Dickins		i915_gem_free_all_phys_object(dev);
222879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		i915_gem_cleanup_ringbuffer(dev);
222979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes		mutex_unlock(&dev->struct_mutex);
22301d2a314c97ceaf383de8e23cdde46729927d433cDaniel Vetter		i915_gem_cleanup_aliasing_ppgtt(dev);
223120bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes		if (I915_HAS_FBC(dev) && i915_powersave)
223220bf377e679208ba9ae0edcb8c70a8f6d33d17f9Jesse Barnes			i915_cleanup_compression(dev);
2233fe669bf88e9108b96a847385df08c9b1e98c1420Chris Wilson		drm_mm_takedown(&dev_priv->mm.stolen);
223402e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter
223502e792fbaadb75dec8e476a05b610e49908fc6a4Daniel Vetter		intel_cleanup_overlay(dev);
2236c2873e9633fe908dccd36dbb1d370e9c59a1ca62Keith Packard
2237c2873e9633fe908dccd36dbb1d370e9c59a1ca62Keith Packard		if (!I915_NEED_GFX_HWS(dev))
2238c2873e9633fe908dccd36dbb1d370e9c59a1ca62Keith Packard			i915_free_hws(dev);
223979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
224079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes
2241701394cc534a4a7883ddc4f8f82fb438b3d664ffDaniel Vetter	if (dev_priv->regs != NULL)
22426dda569fe0fb71a03e2a2e815761796f98232cdbChris Wilson		pci_iounmap(dev->pdev, dev_priv->regs);
2243701394cc534a4a7883ddc4f8f82fb438b3d664ffDaniel Vetter
2244f899fc64cda8569d0529452aafc0da31c042df2eChris Wilson	intel_teardown_gmbus(dev);
2245c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang	intel_teardown_mchbar(dev);
2246c4804411691bdd7d8a57e942cbb502fd52a90074Zhenyu Wang
2247bc0c7f14432f7f94b16f972f2d23b8c1248249b4Daniel Vetter	destroy_workqueue(dev_priv->wq);
2248bc0c7f14432f7f94b16f972f2d23b8c1248249b4Daniel Vetter
2249ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie	pci_dev_put(dev_priv->bridge_dev);
22509a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt	kfree(dev->dev_private);
2251ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
225222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie	return 0;
225322eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie}
225422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie
2255f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilsonint i915_driver_open(struct drm_device *dev, struct drm_file *file)
2256673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
2257f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	struct drm_i915_file_private *file_priv;
2258673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
22598a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui	DRM_DEBUG_DRIVER("\n");
2260f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
2261f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	if (!file_priv)
2262673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt		return -ENOMEM;
2263673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
2264f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	file->driver_priv = file_priv;
2265673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
22661c25595f8d31392b8c36b54c624d01591dbfb87bChris Wilson	spin_lock_init(&file_priv->mm.lock);
2267f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	INIT_LIST_HEAD(&file_priv->mm.request_list);
2268673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
2269673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	return 0;
2270673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
2271673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
227279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/**
227379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_lastclose - clean up after all DRM clients have exited
227479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device
227579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
227679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Take care of cleaning up after all DRM clients have exited.  In the
227779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * mode setting case, we want to restore the kernel's initial mode (just
227879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * in case the last client left us in a bad state).
227979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *
228079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Additionally, in the non-mode setting case, we'll tear down the AGP
228179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * and DMA structures, since the kernel won't be using them, and clea
228279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * up any GEM state.
228379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */
228484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev)
22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2286ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes	drm_i915_private_t *dev_priv = dev->dev_private;
2287ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes
228879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
2289e8e7a2b8ccfdae0d4cb6bd25824bbedcd42da316Dave Airlie		intel_fb_restore_mode(dev);
22906a9ee8af344e3bd7dbd61e67037096cdf7f83289Dave Airlie		vga_switcheroo_process_delayed_switch();
2291144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie		return;
229279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes	}
2293144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie
2294673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt	i915_gem_lastclose(dev);
2295673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
2296b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie	i915_dma_cleanup(dev);
22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22996c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301b962442e46a9340bdbc6711982c59ff0cc2b5afbEric Anholt	i915_gem_release(dev, file_priv);
23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2304f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilsonvoid i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
2305673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{
2306f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	struct drm_i915_file_private *file_priv = file->driver_priv;
2307673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
2308f787a5f59e1b0e320a6b0a37e9a2e306551d1e40Chris Wilson	kfree(file_priv);
2309673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt}
2310673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt
2311c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = {
23121b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
23131b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_FLUSH, i915_flush_ioctl, DRM_AUTH),
23141b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_FLIP, i915_flip_bufs, DRM_AUTH),
23151b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH),
23161b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH),
23171b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH),
23181b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH),
23191b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
2320b2c606fe1defd1fb79612b48b528b2568c97def7Daniel Vetter	DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH),
2321b2c606fe1defd1fb79612b48b528b2568c97def7Daniel Vetter	DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH),
2322b2c606fe1defd1fb79612b48b528b2568c97def7Daniel Vetter	DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
23231b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH),
2324b2c606fe1defd1fb79612b48b528b2568c97def7Daniel Vetter	DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP,  drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
23251b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE,  i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
23261b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE,  i915_vblank_pipe_get, DRM_AUTH),
23271b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH),
23281b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
23291b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
23301b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH|DRM_UNLOCKED),
23311b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_EXECBUFFER2, i915_gem_execbuffer2, DRM_AUTH|DRM_UNLOCKED),
23321b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
23331b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY|DRM_UNLOCKED),
23341b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH|DRM_UNLOCKED),
23351b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH|DRM_UNLOCKED),
23361b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
23371b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
23381b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_UNLOCKED),
23391b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_UNLOCKED),
23401b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_UNLOCKED),
23411b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_UNLOCKED),
23421b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_UNLOCKED),
23431b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_UNLOCKED),
23441b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_UNLOCKED),
23451b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling, DRM_UNLOCKED),
23461b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling, DRM_UNLOCKED),
23471b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_UNLOCKED),
23481b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, DRM_UNLOCKED),
23491b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_UNLOCKED),
23501b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_OVERLAY_PUT_IMAGE, intel_overlay_put_image, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
23511b2f1489633888d4a06028315dc19d65768a1c05Dave Airlie	DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
23528ea30864229e54b01ac0e9fe88c4b733a940ec4eJesse Barnes	DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
23538ea30864229e54b01ac0e9fe88c4b733a940ec4eJesse Barnes	DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, intel_sprite_get_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
2354c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie};
2355c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie
2356c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
2357cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie
2358cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/**
2359cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not.
2360cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
2361cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really
2362cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e.
2363cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
2364cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev   The device to be tested.
2365cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie *
2366cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns
2367cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP.
2368cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */
236984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev)
2370cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{
2371cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie	return 1;
2372cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie}
2373