2 * Copyright (C) 2013-2017 Oracle Corporation
3 * This file is based on ast_drv.c
4 * Copyright 2012 Red Hat Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
26 * Authors: Dave Airlie <airlied@redhat.com>
27 * Michael Thayer <michael.thayer@oracle.com,
28 * Hans de Goede <hdegoede@redhat.com>
30 #include <linux/module.h>
31 #include <linux/console.h>
32 #include <linux/vt_kern.h>
35 #include <drm/drm_crtc_helper.h>
39 int vbox_modeset
= -1;
41 MODULE_PARM_DESC(modeset
, "Disable/Enable modesetting");
42 module_param_named(modeset
, vbox_modeset
, int, 0400);
44 static struct drm_driver driver
;
46 static const struct pci_device_id pciidlist
[] = {
47 { 0x80ee, 0xbeef, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
50 MODULE_DEVICE_TABLE(pci
, pciidlist
);
52 static int vbox_pci_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
54 return drm_get_pci_dev(pdev
, ent
, &driver
);
57 static void vbox_pci_remove(struct pci_dev
*pdev
)
59 struct drm_device
*dev
= pci_get_drvdata(pdev
);
64 static int vbox_drm_freeze(struct drm_device
*dev
)
66 struct vbox_private
*vbox
= dev
->dev_private
;
68 drm_kms_helper_poll_disable(dev
);
70 pci_save_state(dev
->pdev
);
72 drm_fb_helper_set_suspend_unlocked(&vbox
->fbdev
->helper
, true);
77 static int vbox_drm_thaw(struct drm_device
*dev
)
79 struct vbox_private
*vbox
= dev
->dev_private
;
81 drm_mode_config_reset(dev
);
82 drm_helper_resume_force_mode(dev
);
83 drm_fb_helper_set_suspend_unlocked(&vbox
->fbdev
->helper
, false);
88 static int vbox_drm_resume(struct drm_device
*dev
)
92 if (pci_enable_device(dev
->pdev
))
95 ret
= vbox_drm_thaw(dev
);
99 drm_kms_helper_poll_enable(dev
);
104 static int vbox_pm_suspend(struct device
*dev
)
106 struct pci_dev
*pdev
= to_pci_dev(dev
);
107 struct drm_device
*ddev
= pci_get_drvdata(pdev
);
110 error
= vbox_drm_freeze(ddev
);
114 pci_disable_device(pdev
);
115 pci_set_power_state(pdev
, PCI_D3hot
);
120 static int vbox_pm_resume(struct device
*dev
)
122 struct drm_device
*ddev
= pci_get_drvdata(to_pci_dev(dev
));
124 return vbox_drm_resume(ddev
);
127 static int vbox_pm_freeze(struct device
*dev
)
129 struct pci_dev
*pdev
= to_pci_dev(dev
);
130 struct drm_device
*ddev
= pci_get_drvdata(pdev
);
132 if (!ddev
|| !ddev
->dev_private
)
135 return vbox_drm_freeze(ddev
);
138 static int vbox_pm_thaw(struct device
*dev
)
140 struct drm_device
*ddev
= pci_get_drvdata(to_pci_dev(dev
));
142 return vbox_drm_thaw(ddev
);
145 static int vbox_pm_poweroff(struct device
*dev
)
147 struct drm_device
*ddev
= pci_get_drvdata(to_pci_dev(dev
));
149 return vbox_drm_freeze(ddev
);
152 static const struct dev_pm_ops vbox_pm_ops
= {
153 .suspend
= vbox_pm_suspend
,
154 .resume
= vbox_pm_resume
,
155 .freeze
= vbox_pm_freeze
,
156 .thaw
= vbox_pm_thaw
,
157 .poweroff
= vbox_pm_poweroff
,
158 .restore
= vbox_pm_resume
,
161 static struct pci_driver vbox_pci_driver
= {
163 .id_table
= pciidlist
,
164 .probe
= vbox_pci_probe
,
165 .remove
= vbox_pci_remove
,
166 .driver
.pm
= &vbox_pm_ops
,
169 static const struct file_operations vbox_fops
= {
170 .owner
= THIS_MODULE
,
172 .release
= drm_release
,
173 .unlocked_ioctl
= drm_ioctl
,
177 .compat_ioctl
= drm_compat_ioctl
,
182 static int vbox_master_set(struct drm_device
*dev
,
183 struct drm_file
*file_priv
, bool from_open
)
185 struct vbox_private
*vbox
= dev
->dev_private
;
188 * We do not yet know whether the new owner can handle hotplug, so we
189 * do not advertise dynamic modes on the first query and send a
190 * tentative hotplug notification after that to see if they query again.
192 vbox
->initial_mode_queried
= false;
194 mutex_lock(&vbox
->hw_mutex
);
196 * Disable VBVA when someone releases master in case the next person
197 * tries tries to do VESA.
199 /** @todo work out if anyone is likely to and whether it will work. */
201 * Update: we also disable it because if the new master does not do
202 * dirty rectangle reporting (e.g. old versions of Plymouth) then at
203 * least the first screen will still be updated. We enable it as soon
204 * as we receive a dirty rectangle report.
206 vbox_disable_accel(vbox
);
207 mutex_unlock(&vbox
->hw_mutex
);
212 static void vbox_master_drop(struct drm_device
*dev
, struct drm_file
*file_priv
)
214 struct vbox_private
*vbox
= dev
->dev_private
;
216 /* See vbox_master_set() */
217 vbox
->initial_mode_queried
= false;
219 mutex_lock(&vbox
->hw_mutex
);
220 vbox_disable_accel(vbox
);
221 mutex_unlock(&vbox
->hw_mutex
);
224 static struct drm_driver driver
= {
226 DRIVER_MODESET
| DRIVER_GEM
| DRIVER_HAVE_IRQ
| DRIVER_IRQ_SHARED
|
230 .load
= vbox_driver_load
,
231 .unload
= vbox_driver_unload
,
232 .lastclose
= vbox_driver_lastclose
,
233 .master_set
= vbox_master_set
,
234 .master_drop
= vbox_master_drop
,
235 .set_busid
= drm_pci_set_busid
,
238 .irq_handler
= vbox_irq_handler
,
242 .major
= DRIVER_MAJOR
,
243 .minor
= DRIVER_MINOR
,
244 .patchlevel
= DRIVER_PATCHLEVEL
,
246 .gem_free_object
= vbox_gem_free_object
,
247 .dumb_create
= vbox_dumb_create
,
248 .dumb_map_offset
= vbox_dumb_mmap_offset
,
249 .dumb_destroy
= drm_gem_dumb_destroy
,
250 .prime_handle_to_fd
= drm_gem_prime_handle_to_fd
,
251 .prime_fd_to_handle
= drm_gem_prime_fd_to_handle
,
252 .gem_prime_export
= drm_gem_prime_export
,
253 .gem_prime_import
= drm_gem_prime_import
,
254 .gem_prime_pin
= vbox_gem_prime_pin
,
255 .gem_prime_unpin
= vbox_gem_prime_unpin
,
256 .gem_prime_get_sg_table
= vbox_gem_prime_get_sg_table
,
257 .gem_prime_import_sg_table
= vbox_gem_prime_import_sg_table
,
258 .gem_prime_vmap
= vbox_gem_prime_vmap
,
259 .gem_prime_vunmap
= vbox_gem_prime_vunmap
,
260 .gem_prime_mmap
= vbox_gem_prime_mmap
,
263 static int __init
vbox_init(void)
265 #ifdef CONFIG_VGA_CONSOLE
266 if (vgacon_text_force() && vbox_modeset
== -1)
270 if (vbox_modeset
== 0)
273 return drm_pci_init(&driver
, &vbox_pci_driver
);
276 static void __exit
vbox_exit(void)
278 drm_pci_exit(&driver
, &vbox_pci_driver
);
281 module_init(vbox_init
);
282 module_exit(vbox_exit
);
284 MODULE_AUTHOR("Oracle Corporation");
285 MODULE_DESCRIPTION(DRIVER_DESC
);
286 MODULE_LICENSE("GPL and additional rights");