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

30
#include <linux/device.h>
L
Linus Torvalds 已提交
31 32 33 34 35 36
#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
#include "i915_drv.h"

#include "drm_pciids.h"
J
Jesse Barnes 已提交
37 38
#include <linux/console.h>

39
static unsigned int i915_modeset = -1;
J
Jesse Barnes 已提交
40 41 42 43
module_param_named(modeset, i915_modeset, int, 0400);

unsigned int i915_fbpercrtc = 0;
module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
L
Linus Torvalds 已提交
44

45 46
static struct drm_driver driver;

L
Linus Torvalds 已提交
47 48 49 50
static struct pci_device_id pciidlist[] = {
	i915_PCI_IDS
};

J
Jesse Barnes 已提交
51 52 53 54
#if defined(CONFIG_DRM_I915_KMS)
MODULE_DEVICE_TABLE(pci, pciidlist);
#endif

55
static int i915_suspend(struct drm_device *dev, pm_message_t state)
J
Jesse Barnes 已提交
56 57 58 59 60 61 62 63 64
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	if (!dev || !dev_priv) {
		printk(KERN_ERR "dev: %p, dev_priv: %p\n", dev, dev_priv);
		printk(KERN_ERR "DRM not initialized, aborting suspend.\n");
		return -ENODEV;
	}

65 66 67
	if (state.event == PM_EVENT_PRETHAW)
		return 0;

J
Jesse Barnes 已提交
68 69
	pci_save_state(dev->pdev);

70
	i915_save_state(dev);
J
Jesse Barnes 已提交
71

72
	/* If KMS is active, we do the leavevt stuff here */
73 74 75 76 77
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		if (i915_gem_idle(dev))
			dev_err(&dev->pdev->dev,
				"GEM idle failed, resume may fail\n");
		drm_irq_uninstall(dev);
78 79
	}

80
	intel_opregion_free(dev, 1);
81

82 83 84 85 86
	if (state.event == PM_EVENT_SUSPEND) {
		/* Shut down the device */
		pci_disable_device(dev->pdev);
		pci_set_power_state(dev->pdev, PCI_D3hot);
	}
J
Jesse Barnes 已提交
87 88 89 90 91 92

	return 0;
}

static int i915_resume(struct drm_device *dev)
{
93 94 95
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret = 0;

J
Jesse Barnes 已提交
96 97 98 99
	pci_set_power_state(dev->pdev, PCI_D0);
	pci_restore_state(dev->pdev);
	if (pci_enable_device(dev->pdev))
		return -1;
100
	pci_set_master(dev->pdev);
J
Jesse Barnes 已提交
101

102
	i915_restore_state(dev);
J
Jesse Barnes 已提交
103

104
	intel_opregion_init(dev, 1);
105

106 107 108 109 110 111 112 113 114
	/* KMS EnterVT equivalent */
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		mutex_lock(&dev->struct_mutex);
		dev_priv->mm.suspended = 0;

		ret = i915_gem_init_ringbuffer(dev);
		if (ret != 0)
			ret = -1;
		mutex_unlock(&dev->struct_mutex);
115 116

		drm_irq_install(dev);
117 118 119
	}

	return ret;
J
Jesse Barnes 已提交
120 121
}

122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
static int __devinit
i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	return drm_get_dev(pdev, ent, &driver);
}

static void
i915_pci_remove(struct pci_dev *pdev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);

	drm_put_dev(dev);
}

static int
i915_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
	struct drm_device *dev = pci_get_drvdata(pdev);

	return i915_suspend(dev, state);
}

static int
i915_pci_resume(struct pci_dev *pdev)
{
	struct drm_device *dev = pci_get_drvdata(pdev);

	return i915_resume(dev);
}

152 153
static struct vm_operations_struct i915_gem_vm_ops = {
	.fault = i915_gem_fault,
154 155
	.open = drm_gem_vm_open,
	.close = drm_gem_vm_close,
156 157
};

L
Linus Torvalds 已提交
158
static struct drm_driver driver = {
D
Dave Airlie 已提交
159 160 161
	/* don't use mtrr's here, the Xserver or user space app should
	 * deal with them for intel hardware.
	 */
162 163 164
	.driver_features =
	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
165
	.load = i915_driver_load,
J
Jesse Barnes 已提交
166
	.unload = i915_driver_unload,
167
	.open = i915_driver_open,
168 169
	.lastclose = i915_driver_lastclose,
	.preclose = i915_driver_preclose,
170
	.postclose = i915_driver_postclose,
J
Jesse Barnes 已提交
171 172
	.suspend = i915_suspend,
	.resume = i915_resume,
173
	.device_is_agp = i915_driver_device_is_agp,
174 175
	.enable_vblank = i915_enable_vblank,
	.disable_vblank = i915_disable_vblank,
L
Linus Torvalds 已提交
176 177 178 179 180 181 182
	.irq_preinstall = i915_driver_irq_preinstall,
	.irq_postinstall = i915_driver_irq_postinstall,
	.irq_uninstall = i915_driver_irq_uninstall,
	.irq_handler = i915_driver_irq_handler,
	.reclaim_buffers = drm_core_reclaim_buffers,
	.get_map_ofs = drm_core_get_map_ofs,
	.get_reg_ofs = drm_core_get_reg_ofs,
183 184
	.master_create = i915_master_create,
	.master_destroy = i915_master_destroy,
185 186 187 188
#if defined(CONFIG_DEBUG_FS)
	.debugfs_init = i915_gem_debugfs_init,
	.debugfs_cleanup = i915_gem_debugfs_cleanup,
#endif
189 190
	.gem_init_object = i915_gem_init_object,
	.gem_free_object = i915_gem_free_object,
191
	.gem_vm_ops = &i915_gem_vm_ops,
L
Linus Torvalds 已提交
192 193
	.ioctls = i915_ioctls,
	.fops = {
D
Dave Airlie 已提交
194 195 196 197
		 .owner = THIS_MODULE,
		 .open = drm_open,
		 .release = drm_release,
		 .ioctl = drm_ioctl,
198
		 .mmap = drm_gem_mmap,
D
Dave Airlie 已提交
199 200
		 .poll = drm_poll,
		 .fasync = drm_fasync,
201
#ifdef CONFIG_COMPAT
D
Dave Airlie 已提交
202
		 .compat_ioctl = i915_compat_ioctl,
203
#endif
204 205
	},

L
Linus Torvalds 已提交
206
	.pci_driver = {
207 208
		 .name = DRIVER_NAME,
		 .id_table = pciidlist,
209 210 211 212 213 214
		 .probe = i915_pci_probe,
		 .remove = i915_pci_remove,
#ifdef CONFIG_PM
		 .resume = i915_pci_resume,
		 .suspend = i915_pci_suspend,
#endif
215
	},
D
Dave Airlie 已提交
216

217 218 219 220 221 222
	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
	.major = DRIVER_MAJOR,
	.minor = DRIVER_MINOR,
	.patchlevel = DRIVER_PATCHLEVEL,
L
Linus Torvalds 已提交
223 224 225 226 227
};

static int __init i915_init(void)
{
	driver.num_ioctls = i915_max_ioctl;
J
Jesse Barnes 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

	/*
	 * If CONFIG_DRM_I915_KMS is set, default to KMS unless
	 * explicitly disabled with the module pararmeter.
	 *
	 * Otherwise, just follow the parameter (defaulting to off).
	 *
	 * Allow optional vga_text_mode_force boot option to override
	 * the default behavior.
	 */
#if defined(CONFIG_DRM_I915_KMS)
	if (i915_modeset != 0)
		driver.driver_features |= DRIVER_MODESET;
#endif
	if (i915_modeset == 1)
		driver.driver_features |= DRIVER_MODESET;

#ifdef CONFIG_VGA_CONSOLE
	if (vgacon_text_force() && i915_modeset == -1)
		driver.driver_features &= ~DRIVER_MODESET;
#endif

L
Linus Torvalds 已提交
250 251 252 253 254 255 256 257 258 259 260
	return drm_init(&driver);
}

static void __exit i915_exit(void)
{
	drm_exit(&driver);
}

module_init(i915_init);
module_exit(i915_exit);

D
Dave Airlie 已提交
261 262
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
L
Linus Torvalds 已提交
263
MODULE_LICENSE("GPL and additional rights");