qxl_drv.c revision b0e898ac555e96e7863a5ee95d70f3625f1db5e2
1a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek/* vim: set ts=8 sw=8 tw=78 ai noexpandtab */
2ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek/* qxl_drv.c -- QXL driver -*- linux-c -*-
3ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek *
4a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * Copyright 2011 Red Hat, Inc.
5a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * All Rights Reserved.
6a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek *
7a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * Permission is hereby granted, free of charge, to any person obtaining a
8a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * copy of this software and associated documentation files (the "Software"),
9a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * to deal in the Software without restriction, including without limitation
10a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * and/or sell copies of the Software, and to permit persons to whom the
12a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * Software is furnished to do so, subject to the following conditions:
13a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek *
14a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * The above copyright notice and this permission notice (including the next
15a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * paragraph) shall be included in all copies or substantial portions of the
16a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * Software.
17a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek *
18a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * OTHER DEALINGS IN THE SOFTWARE.
25a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek *
26a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek * Authors:
27a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek *    Dave Airlie <airlie@redhat.com>
28a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek *    Alon Levy <alevy@redhat.com>
29a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek */
30a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
31a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include <linux/module.h>
32a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include <linux/console.h>
33a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
34a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include "drmP.h"
35a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include "drm/drm.h"
36a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include "drm_crtc_helper.h"
37a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include "qxl_drv.h"
38a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#include "qxl_object.h"
39a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
40a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekextern int qxl_max_ioctls;
41a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
42a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	{ 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8,
43a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	  0xffff00, 0 },
44ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek	{ 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_OTHER << 8,
45ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek	  0xffff00, 0 },
46a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	{ 0, 0, 0 },
47ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek};
48ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert BuytenhekMODULE_DEVICE_TABLE(pci, pciidlist);
49ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek
50a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_modeset = -1;
51a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekint qxl_num_crtc = 4;
52a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
53a66098daacee2f354dab311b58011e7076aa248cLennert BuytenhekMODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
54a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekmodule_param_named(modeset, qxl_modeset, int, 0400);
55a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
56a66098daacee2f354dab311b58011e7076aa248cLennert BuytenhekMODULE_PARM_DESC(num_heads, "Number of virtual crtcs to expose (default 4)");
57a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekmodule_param_named(num_heads, qxl_num_crtc, int, 0400);
58ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek
59ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhekstatic struct drm_driver qxl_driver;
60ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhekstatic struct pci_driver qxl_pci_driver;
61ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek
62a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int
63a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekqxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
64a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
65a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	if (pdev->revision < 4) {
66a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		DRM_ERROR("qxl too old, doesn't support client_monitors_config,"
67a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek			  " use xf86-video-qxl in user mode");
68a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		return -EINVAL; /* TODO: ENODEV ? */
69ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek	}
70ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek	return drm_get_pci_dev(pdev, ent, &qxl_driver);
71ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek}
72ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek
73ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhekstatic void
74ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhekqxl_pci_remove(struct pci_dev *pdev)
75ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek{
76ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek	struct drm_device *dev = pci_get_drvdata(pdev);
77ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek
78ce9e2e1b8433c8795459a259ee87bc4e424e7c50Lennert Buytenhek	drm_put_dev(dev);
79a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
80a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
81a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic const struct file_operations qxl_fops = {
82a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.owner = THIS_MODULE,
83a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.open = drm_open,
84a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.release = drm_release,
85a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.unlocked_ioctl = drm_ioctl,
86a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.poll = drm_poll,
87a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.mmap = qxl_mmap,
88a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek};
89a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
90a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_drm_freeze(struct drm_device *dev)
91a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
92a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct pci_dev *pdev = dev->pdev;
93a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct qxl_device *qdev = dev->dev_private;
94a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct drm_crtc *crtc;
95a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
96a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	drm_kms_helper_poll_disable(dev);
97a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
98a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	console_lock();
99a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_fbdev_set_suspend(qdev, 1);
100a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	console_unlock();
101a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
102a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	/* unpin the front buffers */
103a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
104a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
105a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		if (crtc->enabled)
106a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek			(*crtc_funcs->disable)(crtc);
107a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	}
108a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
109a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_destroy_monitors_object(qdev);
110a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_surf_evict(qdev);
111a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_vram_evict(qdev);
112a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
113a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	while (!qxl_check_idle(qdev->command_ring));
114a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	while (!qxl_check_idle(qdev->release_ring))
115a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		qxl_queue_garbage_collect(qdev, 1);
116a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
117a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	pci_save_state(pdev);
118a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
119a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return 0;
120a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
121a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
122a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_drm_resume(struct drm_device *dev, bool thaw)
123a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
12476266b2ad38c33fb2c1475cfeb35ed070adaba2bLennert Buytenhek	struct qxl_device *qdev = dev->dev_private;
125a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
126a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qdev->ram_header->int_mask = QXL_INTERRUPT_MASK;
127a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	if (!thaw) {
128a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		qxl_reinit_memslots(qdev);
129a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		qxl_ring_init_hdr(qdev->release_ring);
130a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	}
131a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
132a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_create_monitors_object(qdev);
133a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	drm_helper_resume_force_mode(dev);
134a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
135a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	console_lock();
136a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_fbdev_set_suspend(qdev, 0);
137a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	console_unlock();
138a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
139a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	drm_kms_helper_poll_enable(dev);
140a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return 0;
141a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
142a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
143a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_pm_suspend(struct device *dev)
144a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
145a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct pci_dev *pdev = to_pci_dev(dev);
146a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct drm_device *drm_dev = pci_get_drvdata(pdev);
147618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek	int error;
148618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek
149618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek	error = qxl_drm_freeze(drm_dev);
150618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek	if (error)
151618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek		return error;
152618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek
153618952a7b19b796fce98364fb26551cbe3e16a75Lennert Buytenhek	pci_disable_device(pdev);
154a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	pci_set_power_state(pdev, PCI_D3hot);
155a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return 0;
156a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
157a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
158a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_pm_resume(struct device *dev)
159a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
160a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct pci_dev *pdev = to_pci_dev(dev);
161a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct drm_device *drm_dev = pci_get_drvdata(pdev);
162a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
163a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	pci_set_power_state(pdev, PCI_D0);
164a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	pci_restore_state(pdev);
165a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	if (pci_enable_device(pdev)) {
166a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		return -EIO;
167a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	}
168a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
169a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return qxl_drm_resume(drm_dev, false);
170a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
171a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
172a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_pm_thaw(struct device *dev)
173a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
174a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct pci_dev *pdev = to_pci_dev(dev);
175a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct drm_device *drm_dev = pci_get_drvdata(pdev);
176a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
177a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return qxl_drm_resume(drm_dev, true);
178a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
179a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
180a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_pm_freeze(struct device *dev)
181a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
182a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct pci_dev *pdev = to_pci_dev(dev);
183c46563b714b09d44eec4d1fd8a0f53e79ddaa3aaLennert Buytenhek	struct drm_device *drm_dev = pci_get_drvdata(pdev);
18468ce38845c23443b15e374fb7362916c1231278eLennert Buytenhek
1850439b1f55646ea944b0d58337f5065b79a1c1be0Lennert Buytenhek	return qxl_drm_freeze(drm_dev);
186a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
187a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
188a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int qxl_pm_restore(struct device *dev)
189d89173f25228b8795af2d4b53e985cc44c729332Lennert Buytenhek{
190a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct pci_dev *pdev = to_pci_dev(dev);
191a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct drm_device *drm_dev = pci_get_drvdata(pdev);
192a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	struct qxl_device *qdev = drm_dev->dev_private;
193a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
194a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_io_reset(qdev);
195a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return qxl_drm_resume(drm_dev, false);
196a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
197a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
198a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic const struct dev_pm_ops qxl_pm_ops = {
199a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.suspend = qxl_pm_suspend,
200a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.resume = qxl_pm_resume,
201a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.freeze = qxl_pm_freeze,
202a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.thaw = qxl_pm_thaw,
203a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.poweroff = qxl_pm_freeze,
204a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.restore = qxl_pm_restore,
205a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek};
206a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic struct pci_driver qxl_pci_driver = {
207a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	 .name = DRIVER_NAME,
208a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	 .id_table = pciidlist,
209a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	 .probe = qxl_pci_probe,
210a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	 .remove = qxl_pci_remove,
211a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	 .driver.pm = &qxl_pm_ops,
212a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek};
213a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
214a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic struct drm_driver qxl_driver = {
215a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.driver_features = DRIVER_GEM | DRIVER_MODESET |
216d89173f25228b8795af2d4b53e985cc44c729332Lennert Buytenhek			   DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
217d89173f25228b8795af2d4b53e985cc44c729332Lennert Buytenhek	.dev_priv_size = 0,
218a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.load = qxl_driver_load,
219a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.unload = qxl_driver_unload,
220a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
221a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.dumb_create = qxl_mode_dumb_create,
222a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.dumb_map_offset = qxl_mode_dumb_mmap,
223a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.dumb_destroy = drm_gem_dumb_destroy,
224a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#if defined(CONFIG_DEBUG_FS)
225a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.debugfs_init = qxl_debugfs_init,
226a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.debugfs_cleanup = qxl_debugfs_takedown,
227a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#endif
228a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.gem_init_object = qxl_gem_object_init,
229a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.gem_free_object = qxl_gem_object_free,
230a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.gem_open_object = qxl_gem_object_open,
231a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.gem_close_object = qxl_gem_object_close,
232a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.fops = &qxl_fops,
233a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.ioctls = qxl_ioctls,
234a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.irq_handler = qxl_irq_handler,
235a94cc97e14c5750ec2b50b2e4ecdfb0f369ed0f4Lennert Buytenhek	.name = DRIVER_NAME,
236a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.desc = DRIVER_DESC,
237a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.date = DRIVER_DATE,
238a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.major = 0,
239a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.minor = 1,
240a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	.patchlevel = 0,
241a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek};
242a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
243a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic int __init qxl_init(void)
244a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
245a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#ifdef CONFIG_VGA_CONSOLE
246a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	if (vgacon_text_force() && qxl_modeset == -1)
247a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		return -EINVAL;
248a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek#endif
249a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
250a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	if (qxl_modeset == 0)
251a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek		return -EINVAL;
252a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	qxl_driver.num_ioctls = qxl_max_ioctls;
253a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	return drm_pci_init(&qxl_driver, &qxl_pci_driver);
254a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
255a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
256a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekstatic void __exit qxl_exit(void)
257a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek{
258a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek	drm_pci_exit(&qxl_driver, &qxl_pci_driver);
259a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek}
260a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
261a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekmodule_init(qxl_init);
262a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhekmodule_exit(qxl_exit);
263a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek
264a66098daacee2f354dab311b58011e7076aa248cLennert BuytenhekMODULE_AUTHOR(DRIVER_AUTHOR);
265a66098daacee2f354dab311b58011e7076aa248cLennert BuytenhekMODULE_DESCRIPTION(DRIVER_DESC);
266a66098daacee2f354dab311b58011e7076aa248cLennert BuytenhekMODULE_LICENSE("GPL and additional rights");
267a66098daacee2f354dab311b58011e7076aa248cLennert Buytenhek