1 // SPDX-License-Identifier: MIT
3 * Copyright (C) 2013-2017 Oracle Corporation
4 * This file is based on ast_drv.c
5 * Copyright 2012 Red Hat Inc.
6 * Authors: Dave Airlie <airlied@redhat.com>
7 * Michael Thayer <michael.thayer@oracle.com,
8 * Hans de Goede <hdegoede@redhat.com>
10 #include <linux/console.h>
11 #include <linux/module.h>
12 #include <linux/pci.h>
13 #include <linux/vt_kern.h>
15 #include <drm/drm_crtc_helper.h>
16 #include <drm/drm_drv.h>
17 #include <drm/drm_fb_helper.h>
18 #include <drm/drm_file.h>
19 #include <drm/drm_ioctl.h>
20 #include <drm/drm_managed.h>
24 static int vbox_modeset
= -1;
26 MODULE_PARM_DESC(modeset
, "Disable/Enable modesetting");
27 module_param_named(modeset
, vbox_modeset
, int, 0400);
29 static const struct drm_driver driver
;
31 static const struct pci_device_id pciidlist
[] = {
32 { PCI_DEVICE(0x80ee, 0xbeef) },
35 MODULE_DEVICE_TABLE(pci
, pciidlist
);
37 static int vbox_pci_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
39 struct vbox_private
*vbox
;
42 if (!vbox_check_supported(VBE_DISPI_ID_HGSMI
))
45 ret
= drm_fb_helper_remove_conflicting_pci_framebuffers(pdev
, "vboxvideodrmfb");
49 vbox
= devm_drm_dev_alloc(&pdev
->dev
, &driver
,
50 struct vbox_private
, ddev
);
54 vbox
->ddev
.pdev
= pdev
;
55 pci_set_drvdata(pdev
, vbox
);
56 mutex_init(&vbox
->hw_mutex
);
58 ret
= pcim_enable_device(pdev
);
62 ret
= vbox_hw_init(vbox
);
66 ret
= vbox_mm_init(vbox
);
70 ret
= vbox_mode_init(vbox
);
74 ret
= vbox_irq_init(vbox
);
78 ret
= drm_dev_register(&vbox
->ddev
, 0);
82 drm_fbdev_generic_setup(&vbox
->ddev
, 32);
97 static void vbox_pci_remove(struct pci_dev
*pdev
)
99 struct vbox_private
*vbox
= pci_get_drvdata(pdev
);
101 drm_dev_unregister(&vbox
->ddev
);
103 vbox_mode_fini(vbox
);
108 #ifdef CONFIG_PM_SLEEP
109 static int vbox_pm_suspend(struct device
*dev
)
111 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
114 error
= drm_mode_config_helper_suspend(&vbox
->ddev
);
118 pci_save_state(vbox
->ddev
.pdev
);
119 pci_disable_device(vbox
->ddev
.pdev
);
120 pci_set_power_state(vbox
->ddev
.pdev
, PCI_D3hot
);
125 static int vbox_pm_resume(struct device
*dev
)
127 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
129 if (pci_enable_device(vbox
->ddev
.pdev
))
132 return drm_mode_config_helper_resume(&vbox
->ddev
);
135 static int vbox_pm_freeze(struct device
*dev
)
137 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
139 return drm_mode_config_helper_suspend(&vbox
->ddev
);
142 static int vbox_pm_thaw(struct device
*dev
)
144 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
146 return drm_mode_config_helper_resume(&vbox
->ddev
);
149 static int vbox_pm_poweroff(struct device
*dev
)
151 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
153 return drm_mode_config_helper_suspend(&vbox
->ddev
);
156 static const struct dev_pm_ops vbox_pm_ops
= {
157 .suspend
= vbox_pm_suspend
,
158 .resume
= vbox_pm_resume
,
159 .freeze
= vbox_pm_freeze
,
160 .thaw
= vbox_pm_thaw
,
161 .poweroff
= vbox_pm_poweroff
,
162 .restore
= vbox_pm_resume
,
166 static struct pci_driver vbox_pci_driver
= {
168 .id_table
= pciidlist
,
169 .probe
= vbox_pci_probe
,
170 .remove
= vbox_pci_remove
,
171 #ifdef CONFIG_PM_SLEEP
172 .driver
.pm
= &vbox_pm_ops
,
176 DEFINE_DRM_GEM_FOPS(vbox_fops
);
178 static const struct drm_driver driver
= {
180 DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
182 .lastclose
= drm_fb_helper_lastclose
,
185 .irq_handler
= vbox_irq_handler
,
189 .major
= DRIVER_MAJOR
,
190 .minor
= DRIVER_MINOR
,
191 .patchlevel
= DRIVER_PATCHLEVEL
,
196 static int __init
vbox_init(void)
198 #ifdef CONFIG_VGA_CONSOLE
199 if (vgacon_text_force() && vbox_modeset
== -1)
203 if (vbox_modeset
== 0)
206 return pci_register_driver(&vbox_pci_driver
);
209 static void __exit
vbox_exit(void)
211 pci_unregister_driver(&vbox_pci_driver
);
214 module_init(vbox_init
);
215 module_exit(vbox_exit
);
217 MODULE_AUTHOR("Oracle Corporation");
218 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
219 MODULE_DESCRIPTION(DRIVER_DESC
);
220 MODULE_LICENSE("GPL and additional rights");