linux/drivers/gpu/drm/i915/i915_drv.c
<<
>>
Prefs
   1/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
   2 */
   3/*
   4 *
   5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
   6 * All Rights Reserved.
   7 *
   8 * Permission is hereby granted, free of charge, to any person obtaining a
   9 * copy of this software and associated documentation files (the
  10 * "Software"), to deal in the Software without restriction, including
  11 * without limitation the rights to use, copy, modify, merge, publish,
  12 * distribute, sub license, and/or sell copies of the Software, and to
  13 * permit persons to whom the Software is furnished to do so, subject to
  14 * the following conditions:
  15 *
  16 * The above copyright notice and this permission notice (including the
  17 * next paragraph) shall be included in all copies or substantial portions
  18 * of the Software.
  19 *
  20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  23 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
  24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27 *
  28 */
  29
  30#include <linux/device.h>
  31#include "drmP.h"
  32#include "drm.h"
  33#include "i915_drm.h"
  34#include "i915_drv.h"
  35
  36#include "drm_pciids.h"
  37#include <linux/console.h>
  38#include "drm_crtc_helper.h"
  39
  40static int i915_modeset = -1;
  41module_param_named(modeset, i915_modeset, int, 0400);
  42
  43unsigned int i915_fbpercrtc = 0;
  44module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
  45
  46unsigned int i915_powersave = 1;
  47module_param_named(powersave, i915_powersave, int, 0400);
  48
  49static struct drm_driver driver;
  50
  51static struct pci_device_id pciidlist[] = {
  52        i915_PCI_IDS
  53};
  54
  55#if defined(CONFIG_DRM_I915_KMS)
  56MODULE_DEVICE_TABLE(pci, pciidlist);
  57#endif
  58
  59static int i915_suspend(struct drm_device *dev, pm_message_t state)
  60{
  61        struct drm_i915_private *dev_priv = dev->dev_private;
  62
  63        if (!dev || !dev_priv) {
  64                DRM_ERROR("dev: %p, dev_priv: %p\n", dev, dev_priv);
  65                DRM_ERROR("DRM not initialized, aborting suspend.\n");
  66                return -ENODEV;
  67        }
  68
  69        if (state.event == PM_EVENT_PRETHAW)
  70                return 0;
  71
  72        pci_save_state(dev->pdev);
  73
  74        /* If KMS is active, we do the leavevt stuff here */
  75        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
  76                if (i915_gem_idle(dev))
  77                        dev_err(&dev->pdev->dev,
  78                                "GEM idle failed, resume may fail\n");
  79                drm_irq_uninstall(dev);
  80        }
  81
  82        i915_save_state(dev);
  83
  84        intel_opregion_free(dev, 1);
  85
  86        if (state.event == PM_EVENT_SUSPEND) {
  87                /* Shut down the device */
  88                pci_disable_device(dev->pdev);
  89                pci_set_power_state(dev->pdev, PCI_D3hot);
  90        }
  91
  92        /* Modeset on resume, not lid events */
  93        dev_priv->modeset_on_lid = 0;
  94
  95        return 0;
  96}
  97
  98static int i915_resume(struct drm_device *dev)
  99{
 100        struct drm_i915_private *dev_priv = dev->dev_private;
 101        int ret = 0;
 102
 103        if (pci_enable_device(dev->pdev))
 104                return -1;
 105        pci_set_master(dev->pdev);
 106
 107        i915_restore_state(dev);
 108
 109        intel_opregion_init(dev, 1);
 110
 111        /* KMS EnterVT equivalent */
 112        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 113                mutex_lock(&dev->struct_mutex);
 114                dev_priv->mm.suspended = 0;
 115
 116                ret = i915_gem_init_ringbuffer(dev);
 117                if (ret != 0)
 118                        ret = -1;
 119                mutex_unlock(&dev->struct_mutex);
 120
 121                drm_irq_install(dev);
 122        }
 123        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
 124                /* Resume the modeset for every activated CRTC */
 125                drm_helper_resume_force_mode(dev);
 126        }
 127
 128        dev_priv->modeset_on_lid = 0;
 129
 130        return ret;
 131}
 132
 133/**
 134 * i965_reset - reset chip after a hang
 135 * @dev: drm device to reset
 136 * @flags: reset domains
 137 *
 138 * Reset the chip.  Useful if a hang is detected. Returns zero on successful
 139 * reset or otherwise an error code.
 140 *
 141 * Procedure is fairly simple:
 142 *   - reset the chip using the reset reg
 143 *   - re-init context state
 144 *   - re-init hardware status page
 145 *   - re-init ring buffer
 146 *   - re-init interrupt state
 147 *   - re-init display
 148 */
 149int i965_reset(struct drm_device *dev, u8 flags)
 150{
 151        drm_i915_private_t *dev_priv = dev->dev_private;
 152        unsigned long timeout;
 153        u8 gdrst;
 154        /*
 155         * We really should only reset the display subsystem if we actually
 156         * need to
 157         */
 158        bool need_display = true;
 159
 160        mutex_lock(&dev->struct_mutex);
 161
 162        /*
 163         * Clear request list
 164         */
 165        i915_gem_retire_requests(dev);
 166
 167        if (need_display)
 168                i915_save_display(dev);
 169
 170        if (IS_I965G(dev) || IS_G4X(dev)) {
 171                /*
 172                 * Set the domains we want to reset, then the reset bit (bit 0).
 173                 * Clear the reset bit after a while and wait for hardware status
 174                 * bit (bit 1) to be set
 175                 */
 176                pci_read_config_byte(dev->pdev, GDRST, &gdrst);
 177                pci_write_config_byte(dev->pdev, GDRST, gdrst | flags | ((flags == GDRST_FULL) ? 0x1 : 0x0));
 178                udelay(50);
 179                pci_write_config_byte(dev->pdev, GDRST, gdrst & 0xfe);
 180
 181                /* ...we don't want to loop forever though, 500ms should be plenty */
 182               timeout = jiffies + msecs_to_jiffies(500);
 183                do {
 184                        udelay(100);
 185                        pci_read_config_byte(dev->pdev, GDRST, &gdrst);
 186                } while ((gdrst & 0x1) && time_after(timeout, jiffies));
 187
 188                if (gdrst & 0x1) {
 189                        WARN(true, "i915: Failed to reset chip\n");
 190                        mutex_unlock(&dev->struct_mutex);
 191                        return -EIO;
 192                }
 193        } else {
 194                DRM_ERROR("Error occurred. Don't know how to reset this chip.\n");
 195                return -ENODEV;
 196        }
 197
 198        /* Ok, now get things going again... */
 199
 200        /*
 201         * Everything depends on having the GTT running, so we need to start
 202         * there.  Fortunately we don't need to do this unless we reset the
 203         * chip at a PCI level.
 204         *
 205         * Next we need to restore the context, but we don't use those
 206         * yet either...
 207         *
 208         * Ring buffer needs to be re-initialized in the KMS case, or if X
 209         * was running at the time of the reset (i.e. we weren't VT
 210         * switched away).
 211         */
 212        if (drm_core_check_feature(dev, DRIVER_MODESET) ||
 213            !dev_priv->mm.suspended) {
 214                drm_i915_ring_buffer_t *ring = &dev_priv->ring;
 215                struct drm_gem_object *obj = ring->ring_obj;
 216                struct drm_i915_gem_object *obj_priv = obj->driver_private;
 217                dev_priv->mm.suspended = 0;
 218
 219                /* Stop the ring if it's running. */
 220                I915_WRITE(PRB0_CTL, 0);
 221                I915_WRITE(PRB0_TAIL, 0);
 222                I915_WRITE(PRB0_HEAD, 0);
 223
 224                /* Initialize the ring. */
 225                I915_WRITE(PRB0_START, obj_priv->gtt_offset);
 226                I915_WRITE(PRB0_CTL,
 227                           ((obj->size - 4096) & RING_NR_PAGES) |
 228                           RING_NO_REPORT |
 229                           RING_VALID);
 230                if (!drm_core_check_feature(dev, DRIVER_MODESET))
 231                        i915_kernel_lost_context(dev);
 232                else {
 233                        ring->head = I915_READ(PRB0_HEAD) & HEAD_ADDR;
 234                        ring->tail = I915_READ(PRB0_TAIL) & TAIL_ADDR;
 235                        ring->space = ring->head - (ring->tail + 8);
 236                        if (ring->space < 0)
 237                                ring->space += ring->Size;
 238                }
 239
 240                mutex_unlock(&dev->struct_mutex);
 241                drm_irq_uninstall(dev);
 242                drm_irq_install(dev);
 243                mutex_lock(&dev->struct_mutex);
 244        }
 245
 246        /*
 247         * Display needs restore too...
 248         */
 249        if (need_display)
 250                i915_restore_display(dev);
 251
 252        mutex_unlock(&dev->struct_mutex);
 253        return 0;
 254}
 255
 256
 257static int __devinit
 258i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 259{
 260        return drm_get_dev(pdev, ent, &driver);
 261}
 262
 263static void
 264i915_pci_remove(struct pci_dev *pdev)
 265{
 266        struct drm_device *dev = pci_get_drvdata(pdev);
 267
 268        drm_put_dev(dev);
 269}
 270
 271static int
 272i915_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 273{
 274        struct drm_device *dev = pci_get_drvdata(pdev);
 275
 276        return i915_suspend(dev, state);
 277}
 278
 279static int
 280i915_pci_resume(struct pci_dev *pdev)
 281{
 282        struct drm_device *dev = pci_get_drvdata(pdev);
 283
 284        return i915_resume(dev);
 285}
 286
 287static struct vm_operations_struct i915_gem_vm_ops = {
 288        .fault = i915_gem_fault,
 289        .open = drm_gem_vm_open,
 290        .close = drm_gem_vm_close,
 291};
 292
 293static struct drm_driver driver = {
 294        /* don't use mtrr's here, the Xserver or user space app should
 295         * deal with them for intel hardware.
 296         */
 297        .driver_features =
 298            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
 299            DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
 300        .load = i915_driver_load,
 301        .unload = i915_driver_unload,
 302        .open = i915_driver_open,
 303        .lastclose = i915_driver_lastclose,
 304        .preclose = i915_driver_preclose,
 305        .postclose = i915_driver_postclose,
 306        .suspend = i915_suspend,
 307        .resume = i915_resume,
 308        .device_is_agp = i915_driver_device_is_agp,
 309        .enable_vblank = i915_enable_vblank,
 310        .disable_vblank = i915_disable_vblank,
 311        .irq_preinstall = i915_driver_irq_preinstall,
 312        .irq_postinstall = i915_driver_irq_postinstall,
 313        .irq_uninstall = i915_driver_irq_uninstall,
 314        .irq_handler = i915_driver_irq_handler,
 315        .reclaim_buffers = drm_core_reclaim_buffers,
 316        .get_map_ofs = drm_core_get_map_ofs,
 317        .get_reg_ofs = drm_core_get_reg_ofs,
 318        .master_create = i915_master_create,
 319        .master_destroy = i915_master_destroy,
 320#if defined(CONFIG_DEBUG_FS)
 321        .debugfs_init = i915_debugfs_init,
 322        .debugfs_cleanup = i915_debugfs_cleanup,
 323#endif
 324        .gem_init_object = i915_gem_init_object,
 325        .gem_free_object = i915_gem_free_object,
 326        .gem_vm_ops = &i915_gem_vm_ops,
 327        .ioctls = i915_ioctls,
 328        .fops = {
 329                 .owner = THIS_MODULE,
 330                 .open = drm_open,
 331                 .release = drm_release,
 332                 .ioctl = drm_ioctl,
 333                 .mmap = drm_gem_mmap,
 334                 .poll = drm_poll,
 335                 .fasync = drm_fasync,
 336#ifdef CONFIG_COMPAT
 337                 .compat_ioctl = i915_compat_ioctl,
 338#endif
 339        },
 340
 341        .pci_driver = {
 342                 .name = DRIVER_NAME,
 343                 .id_table = pciidlist,
 344                 .probe = i915_pci_probe,
 345                 .remove = i915_pci_remove,
 346#ifdef CONFIG_PM
 347                 .resume = i915_pci_resume,
 348                 .suspend = i915_pci_suspend,
 349#endif
 350        },
 351
 352        .name = DRIVER_NAME,
 353        .desc = DRIVER_DESC,
 354        .date = DRIVER_DATE,
 355        .major = DRIVER_MAJOR,
 356        .minor = DRIVER_MINOR,
 357        .patchlevel = DRIVER_PATCHLEVEL,
 358};
 359
 360static int __init i915_init(void)
 361{
 362        driver.num_ioctls = i915_max_ioctl;
 363
 364        i915_gem_shrinker_init();
 365
 366        /*
 367         * If CONFIG_DRM_I915_KMS is set, default to KMS unless
 368         * explicitly disabled with the module pararmeter.
 369         *
 370         * Otherwise, just follow the parameter (defaulting to off).
 371         *
 372         * Allow optional vga_text_mode_force boot option to override
 373         * the default behavior.
 374         */
 375#if defined(CONFIG_DRM_I915_KMS)
 376        if (i915_modeset != 0)
 377                driver.driver_features |= DRIVER_MODESET;
 378#endif
 379        if (i915_modeset == 1)
 380                driver.driver_features |= DRIVER_MODESET;
 381
 382#ifdef CONFIG_VGA_CONSOLE
 383        if (vgacon_text_force() && i915_modeset == -1)
 384                driver.driver_features &= ~DRIVER_MODESET;
 385#endif
 386
 387        return drm_init(&driver);
 388}
 389
 390static void __exit i915_exit(void)
 391{
 392        i915_gem_shrinker_exit();
 393        drm_exit(&driver);
 394}
 395
 396module_init(i915_init);
 397module_exit(i915_exit);
 398
 399MODULE_AUTHOR(DRIVER_AUTHOR);
 400MODULE_DESCRIPTION(DRIVER_DESC);
 401MODULE_LICENSE("GPL and additional rights");
 402
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.