i915_dma.c revision 9216d44dc13b5e858253f06d83ceea25a9b72f4f
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" 3728d520433b6375740990ab99d69b0d0067fd656bDave Airlie#include <linux/vgaarb.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Really want an OS-independent resettable timer. Would like to have 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this loop run for (eg) 3 sec, but have the timer reset every time 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the head pointer changes, so that EBUSY only happens if the ring 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * actually stalls for (eg) 3 seconds. 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_wait_ring(struct drm_device * dev, int n, const char *caller) 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 48d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD; 49d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard u32 last_acthd = I915_READ(acthd_reg); 50d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard u32 acthd; 51585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes u32 last_head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson trace_i915_ring_wait_begin (dev); 551c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson 56d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard for (i = 0; i < 100000; i++) { 57585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 58d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard acthd = I915_READ(acthd_reg); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space = ring->head - (ring->tail + 8); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->space < 0) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space += ring->Size; 621c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson if (ring->space >= n) { 631c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson trace_i915_ring_wait_end (dev); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 651c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson } 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6798787c057fdefdce6230ff46f2c1105835005a4cChris Wilson if (dev->primary->master) { 6898787c057fdefdce6230ff46f2c1105835005a4cChris Wilson struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 6998787c057fdefdce6230ff46f2c1105835005a4cChris Wilson if (master_priv->sarea_priv) 7098787c057fdefdce6230ff46f2c1105835005a4cChris Wilson master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT; 7198787c057fdefdce6230ff46f2c1105835005a4cChris Wilson } 7298787c057fdefdce6230ff46f2c1105835005a4cChris Wilson 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->head != last_head) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 76d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard if (acthd != last_acthd) 77d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard i = 0; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last_head = ring->head; 80d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard last_acthd = acthd; 81d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard msleep_interruptible(10); 82d3a6d4467ca44833bcb4ba1893a7aeaae939e4d5Keith Packard 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 851c5d22f76dc721f3acb7a3dadc657a221e487fb7Chris Wilson trace_i915_ring_wait_end (dev); 8620caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EBUSY; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 890ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson/* As a ringbuffer is only allowed to wrap between instructions, fill 900ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson * the tail with NOOPs. 910ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson */ 920ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilsonint i915_wrap_ring(struct drm_device *dev) 930ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson{ 940ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson drm_i915_private_t *dev_priv = dev->dev_private; 950ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson volatile unsigned int *virt; 960ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson int rem; 970ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson 980ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson rem = dev_priv->ring.Size - dev_priv->ring.tail; 990ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson if (dev_priv->ring.space < rem) { 1000ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson int ret = i915_wait_ring(dev, rem, __func__); 1010ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson if (ret) 1020ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson return ret; 1030ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson } 1040ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson dev_priv->ring.space -= rem; 1050ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson 1060ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson virt = (unsigned int *) 1070ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson (dev_priv->ring.virtual_start + dev_priv->ring.tail); 1080ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson rem /= 4; 1090ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson while (rem--) 1100ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson *virt++ = MI_NOOP; 1110ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson 1120ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson dev_priv->ring.tail = 0; 1130ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson 1140ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson return 0; 1150ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson} 1160ef82af7253c1929a3995f271b8b0db462d1a0c3Chris Wilson 117398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/** 118398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Sets up the hardware status page for devices that need a physical address 119398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * in the register. 120398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */ 1213043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic int i915_init_phys_hws(struct drm_device *dev) 122398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{ 123398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_i915_private_t *dev_priv = dev->dev_private; 124398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Program Hardware Status Page */ 125398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->status_page_dmah = 126398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_pci_alloc(dev, PAGE_SIZE, PAGE_SIZE, 0xffffffff); 127398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 128398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (!dev_priv->status_page_dmah) { 129398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard DRM_ERROR("Can not allocate hardware status page\n"); 130398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard return -ENOMEM; 131398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 132398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; 133398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; 134398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 135398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 136398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 137398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 1388a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("Enabled hardware status page\n"); 139398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard return 0; 140398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard} 141398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 142398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard/** 143398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * Frees the hardware status page, whether it's a physical address or a virtual 144398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard * address set up by the X Server. 145398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard */ 1463043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholtstatic void i915_free_hws(struct drm_device *dev) 147398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard{ 148398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_i915_private_t *dev_priv = dev->dev_private; 149398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (dev_priv->status_page_dmah) { 150398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_pci_free(dev, dev_priv->status_page_dmah); 151398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->status_page_dmah = NULL; 152398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 153398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 154398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (dev_priv->status_gfx_addr) { 155398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard dev_priv->status_gfx_addr = 0; 156398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard drm_core_ioremapfree(&dev_priv->hws_map, dev); 157398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 158398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 159398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Need to rewrite hardware status page */ 160398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard I915_WRITE(HWS_PGA, 0x1ffff000); 161398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard} 162398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard 16384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_kernel_lost_context(struct drm_device * dev) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 1667c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_ring_buffer_t *ring = &(dev_priv->ring); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* 17079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * We should never lose context on the ring with modesetting 17179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * as we don't expose it to userspace 17279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 17379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (drm_core_check_feature(dev, DRIVER_MODESET)) 17479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return; 17579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 176585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR; 177585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space = ring->head - (ring->tail + 8); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ring->space < 0) 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ring->space += ring->Size; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!dev->primary->master) 1837c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return; 1847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 1857c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv = dev->primary->master->driver_priv; 1867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (ring->head == ring->tail && master_priv->sarea_priv) 1877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_cleanup(struct drm_device * dev) 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 192ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make sure interrupts are disabled here because the uninstall ioctl 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * may not have been called from userspace and after dev_private 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is freed, it's too late. 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 197ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt if (dev->irq_enabled) 198b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie drm_irq_uninstall(dev); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 200ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes if (dev_priv->ring.virtual_start) { 201ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_core_ioremapfree(&dev_priv->ring.map, dev); 2023043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt dev_priv->ring.virtual_start = NULL; 2033043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt dev_priv->ring.map.handle = NULL; 204ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes dev_priv->ring.map.size = 0; 205ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes } 206dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 207398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Clear the HWS virtual address at teardown */ 208398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (I915_NEED_GFX_HWS(dev)) 209398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard i915_free_hws(dev); 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 214ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesstatic int i915_initialize(struct drm_device * dev, drm_i915_init_t * init) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 216ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 2177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2193a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie master_priv->sarea = drm_getsarea(dev); 2203a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie if (master_priv->sarea) { 2213a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie master_priv->sarea_priv = (drm_i915_sarea_t *) 2223a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie ((u8 *)master_priv->sarea->handle + init->sarea_priv_offset); 2233a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie } else { 2248a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("sarea not found assuming DRI2 userspace\n"); 2253a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie } 2263a03ac1a0223f779a3de313523408ddb099e5679Dave Airlie 227673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (init->ring_size != 0) { 228673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (dev_priv->ring.ring_obj != NULL) { 229673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_dma_cleanup(dev); 230673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_ERROR("Client tried to initialize ringbuffer in " 231673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt "GEM mode\n"); 232673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return -EINVAL; 233673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt } 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 235673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.Size = init->ring_size; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 237673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.offset = init->ring_start; 238673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.size = init->ring_size; 239673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.type = 0; 240673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.flags = 0; 241673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->ring.map.mtrr = 0; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2436fb88588555a18792a27f483887fe1f2af5f9c9bJesse Barnes drm_core_ioremap_wc(&dev_priv->ring.map, dev); 244673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 245673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (dev_priv->ring.map.handle == NULL) { 246673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_dma_cleanup(dev); 247673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_ERROR("can not ioremap virtual address for" 248673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt " ring buffer\n"); 249673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return -ENOMEM; 250673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt } 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->ring.virtual_start = dev_priv->ring.map.handle; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 255a6b54f3f5050c0cbc0c35dd48064846c6302706bMichel Dänzer dev_priv->cpp = init->cpp; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->back_offset = init->back_offset; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->front_offset = init->front_offset; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->current_page = 0; 2597c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (master_priv->sarea_priv) 2607c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->pf_current_page = 0; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allow hardware batchbuffers unless told otherwise. 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_priv->allow_batchbuffer = 1; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 26984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dma_resume(struct drm_device * dev) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2738a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("%s\n", __func__); 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev_priv->ring.map.handle == NULL) { 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("can not ioremap virtual address for" 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds " ring buffer\n"); 27820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -ENOMEM; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Program Hardware Status Page */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv->hw_status_page) { 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Can not find hardware status page\n"); 28420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2868a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("hw status page @ %p\n", 287be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao dev_priv->hw_status_page); 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu if (dev_priv->status_gfx_addr != 0) 290585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); 291dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu else 292585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes I915_WRITE(HWS_PGA, dev_priv->dma_status_page); 2938a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("Enabled hardware status page\n"); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 298c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_dma_init(struct drm_device *dev, void *data, 299c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 301c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_init_t *init = data; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retcode = 0; 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 304c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt switch (init->func) { 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_INIT_DMA: 306ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes retcode = i915_initialize(dev, init); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_CLEANUP_DMA: 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retcode = i915_dma_cleanup(dev); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_RESUME_DMA: 3120d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie retcode = i915_dma_resume(dev); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 31520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt retcode = -EINVAL; 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retcode; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Implement basically the same security restrictions as hardware does 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for MI_BATCH_NON_SECURE. These can be made stricter at any time. 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Most of the calculations below involve calculating the size of a 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * particular instruction. It's important to get the size right as 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that tells us where the next instruction to check is. Any illegal 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * instruction detected will be given a size of zero, which is a 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signal to abort the rest of the buffer. 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int do_validate_cmd(int cmd) 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (((cmd >> 29) & 0x7)) { 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0: 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((cmd >> 23) & 0x3f) { 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0: 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* MI_NOOP */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x4: 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; /* MI_FLUSH */ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* disallow everything else */ 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1: 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* reserved */ 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x2: 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xff) + 2; /* 2d commands */ 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3: 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (((cmd >> 24) & 0x1f) <= 0x18) 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch ((cmd >> 24) & 0x1f) { 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1c: 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1d: 356b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie switch ((cmd >> 16) & 0xff) { 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3: 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0x1f) + 2; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x4: 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xf) + 2; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xffff) + 2; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1e: 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd & (1 << 23)) 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0xffff) + 1; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1f: 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cmd & (1 << 23)) == 0) /* inline vertices */ 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cmd & 0x1ffff) + 2; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (cmd & (1 << 17)) /* indirect random */ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cmd & 0xffff) == 0) 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* unknown length, too hard */ 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (((cmd & 0xffff) + 1) / 2) + 1; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 2; /* indirect sequential */ 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int validate_cmd(int cmd) 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = do_validate_cmd(cmd); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 393bc5f4523f772cc7629c5c5a46cf4f2a07a5500b8Dave Airlie/* printk("validate_cmd( %x ): %d\n", cmd, ret); */ 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 398201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtstatic int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords) 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 404de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) 40520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 406de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 407c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane BEGIN_LP_RING((dwords+1)&~1); 408de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < dwords;) { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cmd, sz; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 412201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt cmd = buffer[i]; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) 41520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(cmd); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (++i, --sz) { 420201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt OUT_RING(buffer[i]); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 424de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie if (dwords & 1) 425de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie OUT_RING(0); 426de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 427de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie ADVANCE_LP_RING(); 428de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 432673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint 433673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholti915_emit_box(struct drm_device *dev, 434201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt struct drm_clip_rect *boxes, 435673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt int i, int DR1, int DR4) 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 438201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt struct drm_clip_rect box = boxes[i]; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Bad box %d,%d..%d,%d\n", 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds box.x1, box.y1, box.x2, box.y2); 44420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 447c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane if (IS_I965G(dev)) { 448c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane BEGIN_LP_RING(4); 449c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(GFX_OP_DRAWRECT_INFO_I965); 450c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); 45178eca43d0391f59c3b1505bb7bd38ff45b650aabAndrew Morton OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); 452c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(DR4); 453c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane ADVANCE_LP_RING(); 454c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane } else { 455c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane BEGIN_LP_RING(6); 456c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(GFX_OP_DRAWRECT_INFO); 457c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(DR1); 458c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING((box.x1 & 0xffff) | (box.y1 << 16)); 459c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(((box.x2 - 1) & 0xffff) | ((box.y2 - 1) << 16)); 460c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(DR4); 461c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane OUT_RING(0); 462c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane ADVANCE_LP_RING(); 463c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane } 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 468c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane/* XXX: Emitting the counter should really be moved to part of the IRQ 469c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane * emit. For now, do it in both places: 470c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane */ 471c29b669caae4ed1630ef479e54bdde126a0378ecAlan Hourihane 47284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic void i915_emit_breadcrumb(struct drm_device *dev) 473de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie{ 474de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie drm_i915_private_t *dev_priv = dev->dev_private; 4757c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 476de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie RING_LOCALS; 477de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 478c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg dev_priv->counter++; 479af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie if (dev_priv->counter > 0x7FFFFFFFUL) 480c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg dev_priv->counter = 0; 4817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (master_priv->sarea_priv) 4827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->last_enqueue = dev_priv->counter; 483de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 484de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie BEGIN_LP_RING(4); 485585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes OUT_RING(MI_STORE_DWORD_INDEX); 4860baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 487de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie OUT_RING(dev_priv->counter); 488de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie OUT_RING(0); 489de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie ADVANCE_LP_RING(); 490de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie} 491de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie 49284b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_cmdbuffer(struct drm_device * dev, 493201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt drm_i915_cmdbuffer_t *cmd, 494201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt struct drm_clip_rect *cliprects, 495201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt void *cmdbuf) 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nbox = cmd->num_cliprects; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0, count, ret; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cmd->sz & 0x3) { 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("alignment"); 50220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i915_kernel_lost_context(dev); 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = nbox ? nbox : 1; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < count; i++) { 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < nbox) { 511201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = i915_emit_box(dev, cliprects, i, 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cmd->DR1, cmd->DR4); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 517201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4); 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 522de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie i915_emit_breadcrumb(dev); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 52684b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_dispatch_batchbuffer(struct drm_device * dev, 527201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt drm_i915_batchbuffer_t * batch, 528201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt struct drm_clip_rect *cliprects) 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int nbox = batch->num_cliprects; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i = 0, count; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((batch->start | batch->used) & 0x7) { 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("alignment"); 53720caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i915_kernel_lost_context(dev); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = nbox ? nbox : 1; 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < count; i++) { 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i < nbox) { 546201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt int ret = i915_emit_box(dev, cliprects, i, 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds batch->DR1, batch->DR4); 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5520790d5e148c0747499742a3c09ba5f1c07f9ed0dKeith Packard if (!IS_I830(dev) && !IS_845G(dev)) { 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BEGIN_LP_RING(2); 55421f16289270447673a7263ccc0b22d562fb01ecbDave Airlie if (IS_I965G(dev)) { 55521f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) | MI_BATCH_NON_SECURE_I965); 55621f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(batch->start); 55721f16289270447673a7263ccc0b22d562fb01ecbDave Airlie } else { 55821f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(MI_BATCH_BUFFER_START | (2 << 6)); 55921f16289270447673a7263ccc0b22d562fb01ecbDave Airlie OUT_RING(batch->start | MI_BATCH_NON_SECURE); 56021f16289270447673a7263ccc0b22d562fb01ecbDave Airlie } 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADVANCE_LP_RING(); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BEGIN_LP_RING(4); 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(MI_BATCH_BUFFER); 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(batch->start | MI_BATCH_NON_SECURE); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(batch->start + batch->used - 4); 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OUT_RING(0); 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADVANCE_LP_RING(); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 572de227f5f32775d86e5c780a7cffdd2e08574f7fbDave Airlie i915_emit_breadcrumb(dev); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 577af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airliestatic int i915_dispatch_flip(struct drm_device * dev) 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 5807c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = 5817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie dev->primary->master->driver_priv; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds RING_LOCALS; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5847c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!master_priv->sarea_priv) 585c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg return -EINVAL; 586c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg 5878a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("%s: page=%d pfCurrentPage=%d\n", 588be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao __func__, 589be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao dev_priv->current_page, 590be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao master_priv->sarea_priv->pf_current_page); 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 592af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie i915_kernel_lost_context(dev); 593af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie 594af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie BEGIN_LP_RING(2); 595585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes OUT_RING(MI_FLUSH | MI_READ_FLUSH); 596af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 597af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie ADVANCE_LP_RING(); 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 599af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie BEGIN_LP_RING(6); 600af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP); 601af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 602af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie if (dev_priv->current_page == 0) { 603af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(dev_priv->back_offset); 604af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie dev_priv->current_page = 1; 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 606af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(dev_priv->front_offset); 607af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie dev_priv->current_page = 0; 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 609af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 610af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie ADVANCE_LP_RING(); 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 612af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie BEGIN_LP_RING(2); 613af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP); 614af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 615af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie ADVANCE_LP_RING(); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6177c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->last_enqueue = dev_priv->counter++; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BEGIN_LP_RING(4); 620585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes OUT_RING(MI_STORE_DWORD_INDEX); 6210baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT); 622af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(dev_priv->counter); 623af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie OUT_RING(0); 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ADVANCE_LP_RING(); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6267c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv->pf_current_page = dev_priv->current_page; 627af6061af0d9f84a4665f88186dc1ff9e4fb78330Dave Airlie return 0; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 63084b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airliestatic int i915_quiescent(struct drm_device * dev) 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i915_kernel_lost_context(dev); 635bf9d89295233ae2ba7b312c78ee5657307b09f4cHarvey Harrison return i915_wait_ring(dev, dev_priv->ring.Size - 8, __func__); 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 638c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flush_ioctl(struct drm_device *dev, void *data, 639c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 641546b0974c39657017407c86fe79811100b60700dEric Anholt int ret; 642546b0974c39657017407c86fe79811100b60700dEric Anholt 643546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 645546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 646546b0974c39657017407c86fe79811100b60700dEric Anholt ret = i915_quiescent(dev); 647546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 648546b0974c39657017407c86fe79811100b60700dEric Anholt 649546b0974c39657017407c86fe79811100b60700dEric Anholt return ret; 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 652c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_batchbuffer(struct drm_device *dev, void *data, 653c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 6567c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 6587c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv; 659c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_batchbuffer_t *batch = data; 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 661201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt struct drm_clip_rect *cliprects = NULL; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv->allow_batchbuffer) { 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("Batchbuffer ioctl disabled\n"); 66520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6688a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("i915 batchbuffer, start %x used %d cliprects %d\n", 669be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao batch->start, batch->used, batch->num_cliprects); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 673201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (batch->num_cliprects < 0) 674201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt return -EINVAL; 675201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 676201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (batch->num_cliprects) { 6779a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt cliprects = kcalloc(batch->num_cliprects, 6789a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt sizeof(struct drm_clip_rect), 6799a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt GFP_KERNEL); 680201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (cliprects == NULL) 681201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt return -ENOMEM; 682201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 683201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = copy_from_user(cliprects, batch->cliprects, 684201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt batch->num_cliprects * 685201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt sizeof(struct drm_clip_rect)); 686201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (ret != 0) 687201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt goto fail_free; 688201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt } 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 690546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 691201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = i915_dispatch_batchbuffer(dev, batch, cliprects); 692546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 694c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg if (sarea_priv) 6950baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 696201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 697201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_free: 6989a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(cliprects); 699201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 703c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_cmdbuffer(struct drm_device *dev, void *data, 704c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 7077c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) 7097c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master_priv->sarea_priv; 710c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_cmdbuffer_t *cmdbuf = data; 711201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt struct drm_clip_rect *cliprects = NULL; 712201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt void *batch_data; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7158a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("i915 cmdbuffer, buf %p sz %d cliprects %d\n", 716be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 718546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 720201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (cmdbuf->num_cliprects < 0) 721201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt return -EINVAL; 722201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 7239a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt batch_data = kmalloc(cmdbuf->sz, GFP_KERNEL); 724201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (batch_data == NULL) 725201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt return -ENOMEM; 726201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 727201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz); 728201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (ret != 0) 729201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt goto fail_batch_free; 730201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 731201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (cmdbuf->num_cliprects) { 7329a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt cliprects = kcalloc(cmdbuf->num_cliprects, 7339a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt sizeof(struct drm_clip_rect), GFP_KERNEL); 734201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (cliprects == NULL) 735201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt goto fail_batch_free; 736201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 737201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = copy_from_user(cliprects, cmdbuf->cliprects, 738201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt cmdbuf->num_cliprects * 739201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt sizeof(struct drm_clip_rect)); 740201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt if (ret != 0) 741201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt goto fail_clip_free; 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 744546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 745201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data); 746546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); 749355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wright goto fail_clip_free; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 752c99b058f132388a666544d293392d52d1def6b12Kristian Høgsberg if (sarea_priv) 7530baf823a10bd4131f70e9712d1f02de3c247f1dfKeith Packard sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); 754201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 755201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholtfail_clip_free: 7569a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(cliprects); 757355d7f370b51bbb6f31aaf9f98861057e1e6bbb2Chris Wrightfail_batch_free: 7589a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(batch_data); 759201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt 760201361a54ed187d8595a283e3a4ddb213bc8323bEric Anholt return ret; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 763c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_flip_bufs(struct drm_device *dev, void *data, 764c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 766546b0974c39657017407c86fe79811100b60700dEric Anholt int ret; 767546b0974c39657017407c86fe79811100b60700dEric Anholt 7688a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("%s\n", __func__); 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 770546b0974c39657017407c86fe79811100b60700dEric Anholt RING_LOCK_TEST_WITH_RETURN(dev, file_priv); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 772546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_lock(&dev->struct_mutex); 773546b0974c39657017407c86fe79811100b60700dEric Anholt ret = i915_dispatch_flip(dev); 774546b0974c39657017407c86fe79811100b60700dEric Anholt mutex_unlock(&dev->struct_mutex); 775546b0974c39657017407c86fe79811100b60700dEric Anholt 776546b0974c39657017407c86fe79811100b60700dEric Anholt return ret; 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 779c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_getparam(struct drm_device *dev, void *data, 780c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 783c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_getparam_t *param = data; 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int value; 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv) { 7873e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh DRM_ERROR("called with no initialization\n"); 78820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt switch (param->param) { 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_PARAM_IRQ_ACTIVE: 7930a3e67a4caac273a3bfc4ced3da364830b1ab241Jesse Barnes value = dev->pdev->irq ? 1 : 0; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_PARAM_ALLOW_BATCHBUFFER: 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds value = dev_priv->allow_batchbuffer ? 1 : 0; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 7980d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie case I915_PARAM_LAST_DISPATCH: 7990d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie value = READ_BREADCRUMB(dev_priv); 8000d6aa60b4ac9689b750e35cd66f5d7c053aff0f4Dave Airlie break; 801ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg case I915_PARAM_CHIPSET_ID: 802ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg value = dev->pci_device; 803ed4c9c4acf948b42b138747fcb8843ecb1a24ce4Kristian Høgsberg break; 804673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt case I915_PARAM_HAS_GEM: 805ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie value = dev_priv->has_gem; 806673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt break; 8070f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes case I915_PARAM_NUM_FENCES_AVAIL: 8080f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes value = dev_priv->num_fence_regs - dev_priv->fence_reg_start; 8090f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes break; 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8118a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("Unknown parameter %d\n", 812be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao param->param); 81320caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 816c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DRM_ERROR("DRM_COPY_TO_USER failed\n"); 81820caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EFAULT; 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 824c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_setparam(struct drm_device *dev, void *data, 825c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds drm_i915_private_t *dev_priv = dev->dev_private; 828c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_setparam_t *param = data; 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev_priv) { 8313e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh DRM_ERROR("called with no initialization\n"); 83220caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 835c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt switch (param->param) { 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_SETPARAM_USE_MI_BATCHBUFFER_START: 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: 839c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt dev_priv->tex_lru_log_granularity = param->value; 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case I915_SETPARAM_ALLOW_BATCHBUFFER: 842c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt dev_priv->allow_batchbuffer = param->value; 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8440f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes case I915_SETPARAM_NUM_USED_FENCES: 8450f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes if (param->value > dev_priv->num_fence_regs || 8460f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes param->value < 0) 8470f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes return -EINVAL; 8480f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes /* Userspace can use first N regs */ 8490f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes dev_priv->fence_reg_start = param->value; 8500f973f27888e4664b253ab2cf69c67c2eb80ab1bJesse Barnes break; 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 8528a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("unknown parameter %d\n", 853be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao param->param); 85420caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 860c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstatic int i915_set_status_page(struct drm_device *dev, void *data, 861c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt struct drm_file *file_priv) 862dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu{ 863dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu drm_i915_private_t *dev_priv = dev->dev_private; 864c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt drm_i915_hws_addr_t *hws = data; 865b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang 866b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang if (!I915_NEED_GFX_HWS(dev)) 867b39d50e53b1bb27f6c29f88a697a4af78427dffdZhenyu Wang return -EINVAL; 868dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 869dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu if (!dev_priv) { 8703e684eae586a9b210a4517da5637a255b1ff5a92Márton Németh DRM_ERROR("called with no initialization\n"); 87120caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -EINVAL; 872dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu } 873dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 87479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (drm_core_check_feature(dev, DRIVER_MODESET)) { 87579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes WARN(1, "tried to set status page when mode setting active\n"); 87679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return 0; 87779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 87879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 8798a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("set status page addr 0x%08x\n", (u32)hws->addr); 880c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt 881c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); 882dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 8838b40958032fd236194de57d29be9cf2c1f2643eeEric Anholt dev_priv->hws_map.offset = dev->agp->base + hws->addr; 884dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.size = 4*1024; 885dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.type = 0; 886dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.flags = 0; 887dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hws_map.mtrr = 0; 888dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 889dd0910b3c71b253c08111110f0399b924a8d5853Dave Airlie drm_core_ioremap_wc(&dev_priv->hws_map, dev); 890dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu if (dev_priv->hws_map.handle == NULL) { 891dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu i915_dma_cleanup(dev); 892dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->status_gfx_addr = 0; 893dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu DRM_ERROR("can not ioremap virtual address for" 894dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu " G33 hw status page\n"); 89520caafa6ecb2487d9b223aa33e7cc704f912a758Eric Anholt return -ENOMEM; 896dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu } 897dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu dev_priv->hw_status_page = dev_priv->hws_map.handle; 898dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 899dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu memset(dev_priv->hw_status_page, 0, PAGE_SIZE); 900585fb111348f7cdc30c6a1b903987612ddeafb23Jesse Barnes I915_WRITE(HWS_PGA, dev_priv->status_gfx_addr); 9018a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n", 902be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao dev_priv->status_gfx_addr); 9038a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("load hws at %p\n", 904be25ed9c5cc06e1d17aa97e41daf88f0b46143e6yakui_zhao dev_priv->hw_status_page); 905dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu return 0; 906dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu} 907dc7a93190c21edbf3ed23e678ad04f852b9cff28Wang Zhenyu 908ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airliestatic int i915_get_bridge_dev(struct drm_device *dev) 909ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie{ 910ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie struct drm_i915_private *dev_priv = dev->dev_private; 911ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie 912ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie dev_priv->bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); 913ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie if (!dev_priv->bridge_dev) { 914ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie DRM_ERROR("bridge device not found\n"); 915ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie return -1; 916ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie } 917ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie return 0; 918ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie} 919ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie 92079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/** 92179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_probe_agp - get AGP bootup configuration 92279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @pdev: PCI device 92379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @aperture_size: returns AGP aperture configured size 92479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @preallocated_size: returns size of BIOS preallocated AGP space 92579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * 92679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Since Intel integrated graphics are UMA, the BIOS has to set aside 92779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * some RAM for the framebuffer at early boot. This code figures out 92879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * how much was set aside so we can use it for our own purposes. 92979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 9302a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholtstatic int i915_probe_agp(struct drm_device *dev, uint32_t *aperture_size, 9318082400327d8d2ca54254b593644942bed0edd25Jesse Barnes uint32_t *preallocated_size, 9328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes uint32_t *start) 93379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{ 934ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie struct drm_i915_private *dev_priv = dev->dev_private; 93579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes u16 tmp = 0; 93679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes unsigned long overhead; 937241fa85b2bb655224357d713c251077dee3585ceEric Anholt unsigned long stolen; 93879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 93979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* Get the fb aperture size and "stolen" memory amount. */ 940ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie pci_read_config_word(dev_priv->bridge_dev, INTEL_GMCH_CTRL, &tmp); 94179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 94279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *aperture_size = 1024 * 1024; 94379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *preallocated_size = 1024 * 1024; 94479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 94560fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt switch (dev->pdev->device) { 94679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case PCI_DEVICE_ID_INTEL_82830_CGC: 94779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case PCI_DEVICE_ID_INTEL_82845G_IG: 94879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case PCI_DEVICE_ID_INTEL_82855GM_IG: 94979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case PCI_DEVICE_ID_INTEL_82865_IG: 95079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M) 95179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *aperture_size *= 64; 95279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes else 95379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes *aperture_size *= 128; 95479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 95579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes default: 95679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* 9xx supports large sizes, just look at the length */ 95760fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt *aperture_size = pci_resource_len(dev->pdev, 2); 95879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 95979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 96079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 96179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* 96279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Some of the preallocated space is taken by the GTT 96379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * and popup. GTT is 1K per MB of aperture size, and popup is 4K. 96479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 9652c07245fb8f7f0a282282e5a9747e46defdb2cc7Zhenyu Wang if (IS_G4X(dev) || IS_IGD(dev) || IS_IGDNG(dev)) 96660fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt overhead = 4096; 96760fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt else 96860fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt overhead = (*aperture_size / 1024) + 4096; 96960fd99e3682c5acc74d58ed61dac93526d6976f7Eric Anholt 970241fa85b2bb655224357d713c251077dee3585ceEric Anholt switch (tmp & INTEL_GMCH_GMS_MASK) { 971241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_855_GMCH_GMS_DISABLED: 972241fa85b2bb655224357d713c251077dee3585ceEric Anholt DRM_ERROR("video memory is disabled\n"); 973241fa85b2bb655224357d713c251077dee3585ceEric Anholt return -1; 97479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_855_GMCH_GMS_STOLEN_1M: 975241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 1 * 1024 * 1024; 976241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 97779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_855_GMCH_GMS_STOLEN_4M: 978241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 4 * 1024 * 1024; 97979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 98079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_855_GMCH_GMS_STOLEN_8M: 981241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 8 * 1024 * 1024; 98279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 98379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_855_GMCH_GMS_STOLEN_16M: 984241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 16 * 1024 * 1024; 98579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 98679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_855_GMCH_GMS_STOLEN_32M: 987241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 32 * 1024 * 1024; 98879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 98979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_915G_GMCH_GMS_STOLEN_48M: 990241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 48 * 1024 * 1024; 99179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 99279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes case INTEL_915G_GMCH_GMS_STOLEN_64M: 993241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 64 * 1024 * 1024; 994241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 995241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_GMCH_GMS_STOLEN_128M: 996241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 128 * 1024 * 1024; 997241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 998241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_GMCH_GMS_STOLEN_256M: 999241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 256 * 1024 * 1024; 1000241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 1001241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_GMCH_GMS_STOLEN_96M: 1002241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 96 * 1024 * 1024; 1003241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 1004241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_GMCH_GMS_STOLEN_160M: 1005241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 160 * 1024 * 1024; 1006241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 1007241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_GMCH_GMS_STOLEN_224M: 1008241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 224 * 1024 * 1024; 1009241fa85b2bb655224357d713c251077dee3585ceEric Anholt break; 1010241fa85b2bb655224357d713c251077dee3585ceEric Anholt case INTEL_GMCH_GMS_STOLEN_352M: 1011241fa85b2bb655224357d713c251077dee3585ceEric Anholt stolen = 352 * 1024 * 1024; 101279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes break; 101379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes default: 101479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes DRM_ERROR("unexpected GMCH_GMS value: 0x%02x\n", 1015241fa85b2bb655224357d713c251077dee3585ceEric Anholt tmp & INTEL_GMCH_GMS_MASK); 101679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return -1; 101779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 1018241fa85b2bb655224357d713c251077dee3585ceEric Anholt *preallocated_size = stolen - overhead; 10198082400327d8d2ca54254b593644942bed0edd25Jesse Barnes *start = overhead; 102079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 102179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return 0; 102279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes} 102379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 10248082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_ADDRESS_MASK 0xfffff000 10258082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */ 10268082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_UNCACHED (0 << 1) 10278082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_DCACHE (1 << 1) /* i830 only */ 10288082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_CACHED (3 << 1) 10298082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_MAPPING_TYPE_MASK (3 << 1) 10308082400327d8d2ca54254b593644942bed0edd25Jesse Barnes#define PTE_VALID (1 << 0) 10318082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes/** 10338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * i915_gtt_to_phys - take a GTT address and turn it into a physical one 10348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * @dev: drm device 10358082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * @gtt_addr: address to translate 10368082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * 10378082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * Some chip functions require allocations from stolen space but need the 10388082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * physical address of the memory in question. We use this routine 10398082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * to get a physical address suitable for register programming from a given 10408082400327d8d2ca54254b593644942bed0edd25Jesse Barnes * GTT address. 10418082400327d8d2ca54254b593644942bed0edd25Jesse Barnes */ 10428082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic unsigned long i915_gtt_to_phys(struct drm_device *dev, 10438082400327d8d2ca54254b593644942bed0edd25Jesse Barnes unsigned long gtt_addr) 10448082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{ 10458082400327d8d2ca54254b593644942bed0edd25Jesse Barnes unsigned long *gtt; 10468082400327d8d2ca54254b593644942bed0edd25Jesse Barnes unsigned long entry, phys; 10478082400327d8d2ca54254b593644942bed0edd25Jesse Barnes int gtt_bar = IS_I9XX(dev) ? 0 : 1; 10488082400327d8d2ca54254b593644942bed0edd25Jesse Barnes int gtt_offset, gtt_size; 10498082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10508082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (IS_I965G(dev)) { 10518082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (IS_G4X(dev) || IS_IGDNG(dev)) { 10528082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_offset = 2*1024*1024; 10538082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_size = 2*1024*1024; 10548082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } else { 10558082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_offset = 512*1024; 10568082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_size = 512*1024; 10578082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 10588082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } else { 10598082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_bar = 3; 10608082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_offset = 0; 10618082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_size = pci_resource_len(dev->pdev, gtt_bar); 10628082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 10638082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10648082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt = ioremap_wc(pci_resource_start(dev->pdev, gtt_bar) + gtt_offset, 10658082400327d8d2ca54254b593644942bed0edd25Jesse Barnes gtt_size); 10668082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (!gtt) { 10678082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_ERROR("ioremap of GTT failed\n"); 10688082400327d8d2ca54254b593644942bed0edd25Jesse Barnes return 0; 10698082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 10708082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10718082400327d8d2ca54254b593644942bed0edd25Jesse Barnes entry = *(volatile u32 *)(gtt + (gtt_addr / 1024)); 10728082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10738082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_DEBUG("GTT addr: 0x%08lx, PTE: 0x%08lx\n", gtt_addr, entry); 10748082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10758082400327d8d2ca54254b593644942bed0edd25Jesse Barnes /* Mask out these reserved bits on this hardware. */ 10768082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev) || 10778082400327d8d2ca54254b593644942bed0edd25Jesse Barnes IS_I945G(dev) || IS_I945GM(dev)) { 10788082400327d8d2ca54254b593644942bed0edd25Jesse Barnes entry &= ~PTE_ADDRESS_MASK_HIGH; 10798082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 10808082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10818082400327d8d2ca54254b593644942bed0edd25Jesse Barnes /* If it's not a mapping type we know, then bail. */ 10828082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if ((entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_UNCACHED && 10838082400327d8d2ca54254b593644942bed0edd25Jesse Barnes (entry & PTE_MAPPING_TYPE_MASK) != PTE_MAPPING_TYPE_CACHED) { 10848082400327d8d2ca54254b593644942bed0edd25Jesse Barnes iounmap(gtt); 10858082400327d8d2ca54254b593644942bed0edd25Jesse Barnes return 0; 10868082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 10878082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10888082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (!(entry & PTE_VALID)) { 10898082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_ERROR("bad GTT entry in stolen space\n"); 10908082400327d8d2ca54254b593644942bed0edd25Jesse Barnes iounmap(gtt); 10918082400327d8d2ca54254b593644942bed0edd25Jesse Barnes return 0; 10928082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 10938082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10948082400327d8d2ca54254b593644942bed0edd25Jesse Barnes iounmap(gtt); 10958082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10968082400327d8d2ca54254b593644942bed0edd25Jesse Barnes phys =(entry & PTE_ADDRESS_MASK) | 10978082400327d8d2ca54254b593644942bed0edd25Jesse Barnes ((uint64_t)(entry & PTE_ADDRESS_MASK_HIGH) << (32 - 4)); 10988082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 10998082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_DEBUG("GTT addr: 0x%08lx, phys addr: 0x%08lx\n", gtt_addr, phys); 11008082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11018082400327d8d2ca54254b593644942bed0edd25Jesse Barnes return phys; 11028082400327d8d2ca54254b593644942bed0edd25Jesse Barnes} 11038082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11048082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic void i915_warn_stolen(struct drm_device *dev) 11058082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{ 11068082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_ERROR("not enough stolen space for compressed buffer, disabling\n"); 11078082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_ERROR("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n"); 11088082400327d8d2ca54254b593644942bed0edd25Jesse Barnes} 11098082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11108082400327d8d2ca54254b593644942bed0edd25Jesse Barnesstatic void i915_setup_compression(struct drm_device *dev, int size) 11118082400327d8d2ca54254b593644942bed0edd25Jesse Barnes{ 11128082400327d8d2ca54254b593644942bed0edd25Jesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 11138082400327d8d2ca54254b593644942bed0edd25Jesse Barnes struct drm_mm_node *compressed_fb, *compressed_llb; 11148082400327d8d2ca54254b593644942bed0edd25Jesse Barnes unsigned long cfb_base, ll_base; 11158082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11168082400327d8d2ca54254b593644942bed0edd25Jesse Barnes /* Leave 1M for line length buffer & misc. */ 11178082400327d8d2ca54254b593644942bed0edd25Jesse Barnes compressed_fb = drm_mm_search_free(&dev_priv->vram, size, 4096, 0); 11188082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (!compressed_fb) { 11198082400327d8d2ca54254b593644942bed0edd25Jesse Barnes i915_warn_stolen(dev); 11208082400327d8d2ca54254b593644942bed0edd25Jesse Barnes return; 11218082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 11228082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11238082400327d8d2ca54254b593644942bed0edd25Jesse Barnes compressed_fb = drm_mm_get_block(compressed_fb, size, 4096); 11248082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (!compressed_fb) { 11258082400327d8d2ca54254b593644942bed0edd25Jesse Barnes i915_warn_stolen(dev); 11268082400327d8d2ca54254b593644942bed0edd25Jesse Barnes return; 11278082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 11288082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 112974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes cfb_base = i915_gtt_to_phys(dev, compressed_fb->start); 113074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes if (!cfb_base) { 113174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); 113274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes drm_mm_put_block(compressed_fb); 11338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 11348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 113574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes if (!IS_GM45(dev)) { 113674dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096, 113774dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes 4096, 0); 113874dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes if (!compressed_llb) { 113974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes i915_warn_stolen(dev); 114074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes return; 114174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes } 114274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes 114374dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes compressed_llb = drm_mm_get_block(compressed_llb, 4096, 4096); 114474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes if (!compressed_llb) { 114574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes i915_warn_stolen(dev); 114674dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes return; 114774dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes } 114874dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes 114974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes ll_base = i915_gtt_to_phys(dev, compressed_llb->start); 115074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes if (!ll_base) { 115174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes DRM_ERROR("failed to get stolen phys addr, disabling FBC\n"); 115274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes drm_mm_put_block(compressed_fb); 115374dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes drm_mm_put_block(compressed_llb); 115474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes } 11558082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 11568082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11578082400327d8d2ca54254b593644942bed0edd25Jesse Barnes dev_priv->cfb_size = size; 11588082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 115974dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes if (IS_GM45(dev)) { 116074dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes g4x_disable_fbc(dev); 116174dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes I915_WRITE(DPFC_CB_BASE, compressed_fb->start); 116274dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes } else { 116374dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes i8xx_disable_fbc(dev); 116474dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes I915_WRITE(FBC_CFB_BASE, cfb_base); 116574dff282237ea8c0a5df1afd8526eac4b6cee063Jesse Barnes I915_WRITE(FBC_LL_BASE, ll_base); 11668082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 11678082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 11688082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base, 11698082400327d8d2ca54254b593644942bed0edd25Jesse Barnes ll_base, size >> 20); 11708082400327d8d2ca54254b593644942bed0edd25Jesse Barnes} 11718082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 117228d520433b6375740990ab99d69b0d0067fd656bDave Airlie/* true = enable decode, false = disable decoder */ 117328d520433b6375740990ab99d69b0d0067fd656bDave Airliestatic unsigned int i915_vga_set_decode(void *cookie, bool state) 117428d520433b6375740990ab99d69b0d0067fd656bDave Airlie{ 117528d520433b6375740990ab99d69b0d0067fd656bDave Airlie struct drm_device *dev = cookie; 117628d520433b6375740990ab99d69b0d0067fd656bDave Airlie 117728d520433b6375740990ab99d69b0d0067fd656bDave Airlie intel_modeset_vga_set_state(dev, state); 117828d520433b6375740990ab99d69b0d0067fd656bDave Airlie if (state) 117928d520433b6375740990ab99d69b0d0067fd656bDave Airlie return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | 118028d520433b6375740990ab99d69b0d0067fd656bDave Airlie VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 118128d520433b6375740990ab99d69b0d0067fd656bDave Airlie else 118228d520433b6375740990ab99d69b0d0067fd656bDave Airlie return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; 118328d520433b6375740990ab99d69b0d0067fd656bDave Airlie} 118428d520433b6375740990ab99d69b0d0067fd656bDave Airlie 11852a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholtstatic int i915_load_modeset_init(struct drm_device *dev, 11868082400327d8d2ca54254b593644942bed0edd25Jesse Barnes unsigned long prealloc_start, 11872a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt unsigned long prealloc_size, 11882a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt unsigned long agp_size) 118979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes{ 119079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 119179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes int fb_bar = IS_I9XX(dev) ? 2 : 0; 119279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes int ret = 0; 119379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 119479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & 119579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 0xff000000; 119679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 11972906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes if (IS_MOBILE(dev) || IS_I9XX(dev)) 119879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes dev_priv->cursor_needs_physical = true; 119979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes else 120079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes dev_priv->cursor_needs_physical = false; 120179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 12022906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes if (IS_I965G(dev) || IS_G33(dev)) 12032906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes dev_priv->cursor_needs_physical = false; 12042906f0258770d3a9c4e65364df8acc904e148bbeJesse Barnes 120579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* Basic memrange allocator for stolen space (aka vram) */ 120679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes drm_mm_init(&dev_priv->vram, 0, prealloc_size); 12078082400327d8d2ca54254b593644942bed0edd25Jesse Barnes DRM_INFO("set up %ldM of stolen space\n", prealloc_size / (1024*1024)); 120879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 120911ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari /* We're off and running w/KMS */ 121011ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari dev_priv->mm.suspended = 0; 121179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 121213f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt /* Let GEM Manage from end of prealloc space to end of aperture. 121313f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * 121413f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * However, leave one page at the end still bound to the scratch page. 121513f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * There are a number of places where the hardware apparently 121613f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * prefetches past the end of the object, and we've seen multiple 121713f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * hangs with the GPU head pointer stuck in a batchbuffer bound 121813f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * at the last page of the aperture. One page should be enough to 121913f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt * keep any prefetching inside of the aperture. 122013f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt */ 122113f4c435ebf2a7c150ffa714f3b23b8e4e8cb42fEric Anholt i915_gem_do_init(dev, prealloc_size, agp_size - 4096); 122279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 122311ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari mutex_lock(&dev->struct_mutex); 122479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes ret = i915_gem_init_ringbuffer(dev); 122511ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari mutex_unlock(&dev->struct_mutex); 122679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (ret) 1227b8da7de56ca0ad34726478a50d138a29a9ff76cbDave Airlie goto out; 122879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 12298082400327d8d2ca54254b593644942bed0edd25Jesse Barnes /* Try to set up FBC with a reasonable compressed buffer size */ 12309216d44dc13b5e858253f06d83ceea25a9b72f4fShaohua Li if (I915_HAS_FBC(dev) && i915_powersave) { 12318082400327d8d2ca54254b593644942bed0edd25Jesse Barnes int cfb_size; 12328082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 12338082400327d8d2ca54254b593644942bed0edd25Jesse Barnes /* Try to get an 8M buffer... */ 12348082400327d8d2ca54254b593644942bed0edd25Jesse Barnes if (prealloc_size > (9*1024*1024)) 12358082400327d8d2ca54254b593644942bed0edd25Jesse Barnes cfb_size = 8*1024*1024; 12368082400327d8d2ca54254b593644942bed0edd25Jesse Barnes else /* fall back to 7/8 of the stolen space */ 12378082400327d8d2ca54254b593644942bed0edd25Jesse Barnes cfb_size = prealloc_size * 7 / 8; 12388082400327d8d2ca54254b593644942bed0edd25Jesse Barnes i915_setup_compression(dev, cfb_size); 12398082400327d8d2ca54254b593644942bed0edd25Jesse Barnes } 12408082400327d8d2ca54254b593644942bed0edd25Jesse Barnes 124179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* Allow hardware batchbuffers unless told otherwise. 124279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 124379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes dev_priv->allow_batchbuffer = 1; 124479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 124579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes ret = intel_init_bios(dev); 124679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (ret) 124779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes DRM_INFO("failed to find VBIOS tables\n"); 124879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 124928d520433b6375740990ab99d69b0d0067fd656bDave Airlie /* if we have > 1 VGA cards, then disable the radeon VGA resources */ 125028d520433b6375740990ab99d69b0d0067fd656bDave Airlie ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); 125128d520433b6375740990ab99d69b0d0067fd656bDave Airlie if (ret) 125228d520433b6375740990ab99d69b0d0067fd656bDave Airlie goto destroy_ringbuffer; 125328d520433b6375740990ab99d69b0d0067fd656bDave Airlie 125479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes ret = drm_irq_install(dev); 125579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (ret) 125679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes goto destroy_ringbuffer; 125779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 125879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* Always safe in the mode setting case. */ 125979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* FIXME: do pre/post-mode set stuff in core KMS code */ 126079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes dev->vblank_disable_allowed = 1; 126179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 126279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes /* 126379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Initialize the hardware status page IRQ location. 126479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 126579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 126679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); 126779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 126879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes intel_modeset_init(dev); 126979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 12707a1fb5d06d3936c0982e2cf8b53b046244a9aad6Jesse Barnes drm_helper_initial_config(dev); 127179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 127279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return 0; 127379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 127479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesdestroy_ringbuffer: 127579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes i915_gem_cleanup_ringbuffer(dev); 127679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout: 127779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return ret; 127879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes} 127979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 12807c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlieint i915_master_create(struct drm_device *dev, struct drm_master *master) 12817c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{ 12827c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv; 12837c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 12849a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL); 12857c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!master_priv) 12867c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return -ENOMEM; 12877c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 12887c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master->driver_priv = master_priv; 12897c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return 0; 12907c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie} 12917c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 12927c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlievoid i915_master_destroy(struct drm_device *dev, struct drm_master *master) 12937c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie{ 12947c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie struct drm_i915_master_private *master_priv = master->driver_priv; 12957c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 12967c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie if (!master_priv) 12977c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie return; 12987c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 12999a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(master_priv); 13007c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 13017c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie master->driver_priv = NULL; 13027c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie} 13037c1c2871a6a3a114853ec6836e9035ac1c0c7f7aDave Airlie 13047662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Listatic void i915_get_mem_freq(struct drm_device *dev) 13057662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li{ 13067662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li drm_i915_private_t *dev_priv = dev->dev_private; 13077662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li u32 tmp; 13087662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li 13097662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li if (!IS_IGD(dev)) 13107662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li return; 13117662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li 13127662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li tmp = I915_READ(CLKCFG); 13137662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li 13147662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li switch (tmp & CLKCFG_FSB_MASK) { 13157662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_FSB_533: 13167662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->fsb_freq = 533; /* 133*4 */ 13177662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13187662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_FSB_800: 13197662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->fsb_freq = 800; /* 200*4 */ 13207662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13217662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_FSB_667: 13227662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->fsb_freq = 667; /* 167*4 */ 13237662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13247662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_FSB_400: 13257662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->fsb_freq = 400; /* 100*4 */ 13267662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13277662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li } 13287662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li 13297662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li switch (tmp & CLKCFG_MEM_MASK) { 13307662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_MEM_533: 13317662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->mem_freq = 533; 13327662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13337662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_MEM_667: 13347662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->mem_freq = 667; 13357662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13367662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li case CLKCFG_MEM_800: 13377662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li dev_priv->mem_freq = 800; 13387662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li break; 13397662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li } 13407662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li} 13417662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li 134279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/** 134379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_load - setup chip and create an initial config 134479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device 134579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @flags: startup flags 134679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * 134779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * The driver load routine has to do several things: 134879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * - drive output discovery via intel_modeset_init() 134979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * - initialize the memory manager 135079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * - allocate initial config memory 135179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * - setup the DRM framebuffer with the allocated memory 135279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 135384b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_load(struct drm_device *dev, unsigned long flags) 135422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie{ 1355ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 1356d883f7f1b75c8dcafa891f7b9e69c5a2f0ff6d66Benjamin Herrenschmidt resource_size_t base, size; 1357ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes int ret = 0, mmio_bar = IS_I9XX(dev) ? 0 : 1; 13588082400327d8d2ca54254b593644942bed0edd25Jesse Barnes uint32_t agp_size, prealloc_size, prealloc_start; 1359ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 136022eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie /* i915 has 4 more counters */ 136122eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->counters += 4; 136222eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[6] = _DRM_STAT_IRQ; 136322eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[7] = _DRM_STAT_PRIMARY; 136422eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[8] = _DRM_STAT_SECONDARY; 136522eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie dev->types[9] = _DRM_STAT_DMA; 136622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie 13679a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt dev_priv = kzalloc(sizeof(drm_i915_private_t), GFP_KERNEL); 1368ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes if (dev_priv == NULL) 1369ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes return -ENOMEM; 1370ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 1371ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes dev->dev_private = (void *)dev_priv; 1372673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt dev_priv->dev = dev; 1373ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 1374ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes /* Add register map (needed for suspend/resume) */ 1375ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes base = drm_get_resource_start(dev, mmio_bar); 1376ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes size = drm_get_resource_len(dev, mmio_bar); 1377ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 1378ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie if (i915_get_bridge_dev(dev)) { 1379ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie ret = -EIO; 1380ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie goto free_priv; 1381ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie } 1382ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie 13833043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt dev_priv->regs = ioremap(base, size); 138479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (!dev_priv->regs) { 138579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes DRM_ERROR("failed to map registers\n"); 138679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes ret = -EIO; 1387ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie goto put_bridge; 138879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 1389ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 1390ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt dev_priv->mm.gtt_mapping = 1391ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt io_mapping_create_wc(dev->agp->base, 1392ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt dev->agp->agp_info.aper_size * 1024*1024); 13936644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi if (dev_priv->mm.gtt_mapping == NULL) { 13946644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi ret = -EIO; 13956644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi goto out_rmmap; 13966644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi } 13976644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi 1398ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt /* Set up a WC MTRR for non-PAT systems. This is more common than 1399ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt * one would think, because the kernel disables PAT on first 1400ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt * generation Core chips because WC PAT gets overridden by a UC 1401ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt * MTRR if present. Even if a UC MTRR isn't present. 1402ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt */ 1403ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base, 1404ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt dev->agp->agp_info.aper_size * 1405ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt 1024 * 1024, 1406ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt MTRR_TYPE_WRCOMB, 1); 1407ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt if (dev_priv->mm.gtt_mtrr < 0) { 1408040aefa263aa9cd7bd5df50586c35e1e15e77f84Eric Anholt DRM_INFO("MTRR allocation failed. Graphics " 1409ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt "performance may suffer.\n"); 1410ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt } 1411ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt 14128082400327d8d2ca54254b593644942bed0edd25Jesse Barnes ret = i915_probe_agp(dev, &agp_size, &prealloc_size, &prealloc_start); 14132a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt if (ret) 14142a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt goto out_iomapfree; 14152a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt 14169c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt dev_priv->wq = create_workqueue("i915"); 14179c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt if (dev_priv->wq == NULL) { 14189c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt DRM_ERROR("Failed to create our workqueue.\n"); 14199c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt ret = -ENOMEM; 14209c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt goto out_iomapfree; 14219c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt } 14229c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt 1423ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie /* enable GEM by default */ 1424ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie dev_priv->has_gem = 1; 1425ac5c4e76180a74c7f922f6fa71ace0cef45fa433Dave Airlie 14262a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt if (prealloc_size > agp_size * 3 / 4) { 14272a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt DRM_ERROR("Detected broken video BIOS with %d/%dkB of video " 14282a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt "memory stolen.\n", 14292a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt prealloc_size / 1024, agp_size / 1024); 14302a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt DRM_ERROR("Disabling GEM. (try reducing stolen memory or " 14312a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt "updating the BIOS to fix).\n"); 14322a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt dev_priv->has_gem = 0; 14332a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt } 14342a34f5e6b61c7e8f3b6f25847bcda88511b0ead4Eric Anholt 14359880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes dev->driver->get_vblank_counter = i915_get_vblank_counter; 143642c2798b35b95c471877133e19ccc3cab00e9b65Jesse Barnes dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ 1437036a4a7d9272582fc7370359515d807393e2f728Zhenyu Wang if (IS_G4X(dev) || IS_IGDNG(dev)) { 143842c2798b35b95c471877133e19ccc3cab00e9b65Jesse Barnes dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ 14399880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes dev->driver->get_vblank_counter = gm45_get_vblank_counter; 144042c2798b35b95c471877133e19ccc3cab00e9b65Jesse Barnes } 14419880b7a527ffbb52f65c2de0a8d4eea86e24775eJesse Barnes 1442673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_gem_load(dev); 1443673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1444398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard /* Init HWS */ 1445398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (!I915_NEED_GFX_HWS(dev)) { 1446398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard ret = i915_init_phys_hws(dev); 1447398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard if (ret != 0) 14489c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt goto out_workqueue_free; 1449398c9cb20b5c6c5d1313912b937d653a46fec578Keith Packard } 1450ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 14517662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li i915_get_mem_freq(dev); 14527662c8bd6545c12ac7b2b39e4554c3ba34789c50Shaohua Li 1453ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt /* On the 945G/GM, the chipset reports the MSI capability on the 1454ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * integrated graphics even though the support isn't actually there 1455ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * according to the published specs. It doesn't appear to function 1456ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * correctly in testing on 945G. 1457ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * This may be a side effect of MSI having been made available for PEG 1458ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt * and the registers being closely associated. 1459d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard * 1460d1ed629f44b3a4108d5c445971535f05f441fce7Keith Packard * According to chipset errata, on the 965GM, MSI interrupts may 1461b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard * be lost or delayed, but we use them anyways to avoid 1462b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard * stuck interrupts on some machines. 1463ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt */ 1464b60678a75d44fa9d5969f79781bd856ad5858609Keith Packard if (!IS_I945G(dev) && !IS_I945GM(dev)) 1465d3e74d0237b102d34979015fbf6df02ca4413074Eric Anholt pci_enable_msi(dev->pdev); 1466ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 1467ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt spin_lock_init(&dev_priv->user_irq_lock); 146863eeaf38251183ec2b1caee11e4a2c040cb5ce6cJesse Barnes spin_lock_init(&dev_priv->error_lock); 146979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes dev_priv->user_irq_refcount = 0; 14709d34e5db07303c9609053e2e651aa6d1fc74e923Chris Wilson dev_priv->trace_irq_seqno = 0; 1471ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 147252440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard ret = drm_vblank_init(dev, I915_NUM_PIPE); 147352440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard 147452440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard if (ret) { 147552440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard (void) i915_driver_unload(dev); 147652440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard return ret; 147752440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard } 147852440211dcdc52c0b757f8b34d122e11b12cdd50Keith Packard 147911ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari /* Start out suspended */ 148011ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari dev_priv->mm.suspended = 1; 148111ed50ec2a316928c2bacc1149bded86c6a96068Ben Gamari 148279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (drm_core_check_feature(dev, DRIVER_MODESET)) { 14838082400327d8d2ca54254b593644942bed0edd25Jesse Barnes ret = i915_load_modeset_init(dev, prealloc_start, 14848082400327d8d2ca54254b593644942bed0edd25Jesse Barnes prealloc_size, agp_size); 148579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (ret < 0) { 148679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes DRM_ERROR("failed to init modeset\n"); 14879c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt goto out_workqueue_free; 148879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 148979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 149079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 149174a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett /* Must be done after probing outputs */ 1492e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang /* FIXME: verify on IGDNG */ 1493e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang if (!IS_IGDNG(dev)) 1494e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang intel_opregion_init(dev, 0); 149574a365b3f354fafc537efa5867deb7a9fadbfe27Matthew Garrett 1496f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, 1497f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari (unsigned long) dev); 149879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes return 0; 149979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 15009c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholtout_workqueue_free: 15019c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt destroy_workqueue(dev_priv->wq); 15026644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadiout_iomapfree: 15036644107d57a8fa82b47e4c55da4d9d91a612f29cVenkatesh Pallipadi io_mapping_free(dev_priv->mm.gtt_mapping); 150479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesout_rmmap: 150579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes iounmap(dev_priv->regs); 1506ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlieput_bridge: 1507ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie pci_dev_put(dev_priv->bridge_dev); 150879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnesfree_priv: 15099a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(dev_priv); 1510ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes return ret; 1511ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes} 1512ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 1513ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnesint i915_driver_unload(struct drm_device *dev) 1514ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes{ 1515ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes struct drm_i915_private *dev_priv = dev->dev_private; 1516ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 15179c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt destroy_workqueue(dev_priv->wq); 1518f65d94211e2bcba17faf05a6a3809af0e4217767Ben Gamari del_timer_sync(&dev_priv->hangcheck_timer); 15199c9fe1f841745184bbc5460c6f3909fded3b929bEric Anholt 1520ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt io_mapping_free(dev_priv->mm.gtt_mapping); 1521ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt if (dev_priv->mm.gtt_mtrr >= 0) { 1522ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, 1523ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt dev->agp->agp_info.aper_size * 1024 * 1024); 1524ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt dev_priv->mm.gtt_mtrr = -1; 1525ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt } 1526ab657db12d7020629f26f30d287558a8d0e32b41Eric Anholt 152779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (drm_core_check_feature(dev, DRIVER_MODESET)) { 152879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes drm_irq_uninstall(dev); 152928d520433b6375740990ab99d69b0d0067fd656bDave Airlie vga_client_register(dev->pdev, NULL, NULL, NULL); 153079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 153179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 1532ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt if (dev->pdev->msi_enabled) 1533ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt pci_disable_msi(dev->pdev); 1534ed4cb4142b242d8090d3811d5eb4abf6aa985bc8Eric Anholt 15353043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt if (dev_priv->regs != NULL) 15363043c60c485ad694392d3f71bd7ef9f5c5f7cfddEric Anholt iounmap(dev_priv->regs); 1537ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 1538e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang if (!IS_IGDNG(dev)) 1539e170b030dcd6aed11dde2d124c09991ec771f529Zhenyu Wang intel_opregion_free(dev, 0); 15408ee1c3db9075cb3211352e737e0feb98fd733b20Matthew Garrett 154179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (drm_core_check_feature(dev, DRIVER_MODESET)) { 154279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes intel_modeset_cleanup(dev); 154379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 154471acb5eb8d95b371f4cdd88a47f3c83c870d1c8fDave Airlie i915_gem_free_all_phys_object(dev); 154571acb5eb8d95b371f4cdd88a47f3c83c870d1c8fDave Airlie 154679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes mutex_lock(&dev->struct_mutex); 154779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes i915_gem_cleanup_ringbuffer(dev); 154879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes mutex_unlock(&dev->struct_mutex); 154979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes drm_mm_takedown(&dev_priv->vram); 155079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes i915_gem_lastclose(dev); 155179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 155279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes 1553ec2a4c3fdc8e82fe82a25d800e85c1ea06b74372Dave Airlie pci_dev_put(dev_priv->bridge_dev); 15549a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(dev->dev_private); 1555ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 155622eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie return 0; 155722eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie} 155822eae947bf76e236ba972f2f11cfd1b083b736adDave Airlie 1559673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtint i915_driver_open(struct drm_device *dev, struct drm_file *file_priv) 1560673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{ 1561673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt struct drm_i915_file_private *i915_file_priv; 1562673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 15638a4c47f346cc7a12d0897c05eb3cc1add26b487fZhao Yakui DRM_DEBUG_DRIVER("\n"); 1564673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_file_priv = (struct drm_i915_file_private *) 15659a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kmalloc(sizeof(*i915_file_priv), GFP_KERNEL); 1566673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1567673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt if (!i915_file_priv) 1568673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return -ENOMEM; 1569673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1570673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt file_priv->driver_priv = i915_file_priv; 1571673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1572b962442e46a9340bdbc6711982c59ff0cc2b5afbEric Anholt INIT_LIST_HEAD(&i915_file_priv->mm.request_list); 1573673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1574673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt return 0; 1575673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt} 1576673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 157779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes/** 157879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * i915_driver_lastclose - clean up after all DRM clients have exited 157979e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * @dev: DRM device 158079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * 158179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Take care of cleaning up after all DRM clients have exited. In the 158279e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * mode setting case, we want to restore the kernel's initial mode (just 158379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * in case the last client left us in a bad state). 158479e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * 158579e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * Additionally, in the non-mode setting case, we'll tear down the AGP 158679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * and DMA structures, since the kernel won't be using them, and clea 158779e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes * up any GEM state. 158879e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes */ 158984b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlievoid i915_driver_lastclose(struct drm_device * dev) 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1591ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 1592ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 159379e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) { 1594785b93ef8c309730c2de84ce9c229e40e2d01480Dave Airlie drm_fb_helper_restore(); 1595144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie return; 159679e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes } 1597144a75fa1faa4a81530bded2e59872ef80d496b6Dave Airlie 1598673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt i915_gem_lastclose(dev); 1599673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1600ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes if (dev_priv->agp_heap) 1601b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie i915_mem_takedown(&(dev_priv->agp_heap)); 1602ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes 1603b5e89ed53ed8d24f83ba1941c07382af00ed238eDave Airlie i915_dma_cleanup(dev); 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16066c340eac0285f3d62406d2d902d0e96fbf2a5dc0Eric Anholtvoid i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1608ba8bbcf6ff4650712f64c0ef61139c73898e2165Jesse Barnes drm_i915_private_t *dev_priv = dev->dev_private; 1609b962442e46a9340bdbc6711982c59ff0cc2b5afbEric Anholt i915_gem_release(dev, file_priv); 161079e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes if (!drm_core_check_feature(dev, DRIVER_MODESET)) 161179e539453b34e35f39299a899d263b0a1f1670bdJesse Barnes i915_mem_release(dev, file_priv, dev_priv->agp_heap); 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1614673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholtvoid i915_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) 1615673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt{ 1616673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; 1617673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 16189a298b2acd771d8a5c0004d8f8e4156c65b11f6bEric Anholt kfree(i915_file_priv); 1619673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt} 1620673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt 1621c153f45f9b7e30289157bba3ff5682291df16caaEric Anholtstruct drm_ioctl_desc i915_ioctls[] = { 1622c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1623c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), 1624c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH), 1625c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), 1626c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), 1627c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), 1628c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH), 1629c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1630c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH), 1631c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH), 1632c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1633c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), 1634c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), 1635c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), 1636c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), 1637c153f45f9b7e30289157bba3ff5682291df16caaEric Anholt DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), 16384b40893918203ee1a1f6a114316c2a19c072e9bdMatthias Hopf DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 16392bdf00b22154023ac312481583603f4724eb1401Dave Airlie DRM_IOCTL_DEF(DRM_I915_GEM_INIT, i915_gem_init_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1640673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_EXECBUFFER, i915_gem_execbuffer, DRM_AUTH), 1641673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_PIN, i915_gem_pin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), 1642673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_UNPIN, i915_gem_unpin_ioctl, DRM_AUTH|DRM_ROOT_ONLY), 1643673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_BUSY, i915_gem_busy_ioctl, DRM_AUTH), 1644673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_THROTTLE, i915_gem_throttle_ioctl, DRM_AUTH), 16452bdf00b22154023ac312481583603f4724eb1401Dave Airlie DRM_IOCTL_DEF(DRM_I915_GEM_ENTERVT, i915_gem_entervt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 16462bdf00b22154023ac312481583603f4724eb1401Dave Airlie DRM_IOCTL_DEF(DRM_I915_GEM_LEAVEVT, i915_gem_leavevt_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 1647673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_CREATE, i915_gem_create_ioctl, 0), 1648673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_PREAD, i915_gem_pread_ioctl, 0), 1649673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_PWRITE, i915_gem_pwrite_ioctl, 0), 1650673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_MMAP, i915_gem_mmap_ioctl, 0), 1651de151cf67ce52ed2d88083daa5e60c7858947329Jesse Barnes DRM_IOCTL_DEF(DRM_I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, 0), 1652673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, 0), 1653673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, 0), 1654673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_SET_TILING, i915_gem_set_tiling, 0), 1655673a394b1e3b69be886ff24abfd6df97c52e8d08Eric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0), 16565a125c3c79167e78ba44efef03af7090ef28eeafEric Anholt DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0), 165708d7b3d1edff84bd673d9e9ab36b5aa62e1ba903Carl Worth DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0), 16583ef94daae7530b4ebcd2e5f48f1028cd2d2470baChris Wilson DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0), 1659c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie}; 1660c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlie 1661c94f70298529d99ac6e1ee7709f61eab00adeb39Dave Airlieint i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); 1662cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie 1663cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie/** 1664cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * Determine if the device really is AGP or not. 1665cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * 1666cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * All Intel graphics chipsets are treated as AGP, even if they are really 1667cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * PCI-e. 1668cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * 1669cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \param dev The device to be tested. 1670cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * 1671cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * \returns 1672cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie * A value of 1 is always retured to indictate every i9x5 is AGP. 1673cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie */ 167484b1fd103dbbe01b5905db1444d3fc8afa9a7207Dave Airlieint i915_driver_device_is_agp(struct drm_device * dev) 1675cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie{ 1676cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie return 1; 1677cda173806644d2af22ffd9896eed8ef99b97d356Dave Airlie} 1678