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>
23 static int vbox_modeset
= -1;
25 MODULE_PARM_DESC(modeset
, "Disable/Enable modesetting");
26 module_param_named(modeset
, vbox_modeset
, int, 0400);
28 static struct drm_driver driver
;
30 static const struct pci_device_id pciidlist
[] = {
31 { PCI_DEVICE(0x80ee, 0xbeef) },
34 MODULE_DEVICE_TABLE(pci
, pciidlist
);
36 static int vbox_pci_probe(struct pci_dev
*pdev
, const struct pci_device_id
*ent
)
38 struct vbox_private
*vbox
;
41 if (!vbox_check_supported(VBE_DISPI_ID_HGSMI
))
44 vbox
= kzalloc(sizeof(*vbox
), GFP_KERNEL
);
48 ret
= drm_dev_init(&vbox
->ddev
, &driver
, &pdev
->dev
);
54 vbox
->ddev
.pdev
= pdev
;
55 vbox
->ddev
.dev_private
= vbox
;
56 pci_set_drvdata(pdev
, vbox
);
57 mutex_init(&vbox
->hw_mutex
);
59 ret
= pci_enable_device(pdev
);
63 ret
= vbox_hw_init(vbox
);
67 ret
= vbox_mm_init(vbox
);
71 ret
= vbox_mode_init(vbox
);
75 ret
= vbox_irq_init(vbox
);
79 ret
= drm_fbdev_generic_setup(&vbox
->ddev
, 32);
83 ret
= drm_dev_register(&vbox
->ddev
, 0);
98 pci_disable_device(pdev
);
100 drm_dev_put(&vbox
->ddev
);
104 static void vbox_pci_remove(struct pci_dev
*pdev
)
106 struct vbox_private
*vbox
= pci_get_drvdata(pdev
);
108 drm_dev_unregister(&vbox
->ddev
);
110 vbox_mode_fini(vbox
);
113 drm_dev_put(&vbox
->ddev
);
116 #ifdef CONFIG_PM_SLEEP
117 static int vbox_pm_suspend(struct device
*dev
)
119 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
122 error
= drm_mode_config_helper_suspend(&vbox
->ddev
);
126 pci_save_state(vbox
->ddev
.pdev
);
127 pci_disable_device(vbox
->ddev
.pdev
);
128 pci_set_power_state(vbox
->ddev
.pdev
, PCI_D3hot
);
133 static int vbox_pm_resume(struct device
*dev
)
135 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
137 if (pci_enable_device(vbox
->ddev
.pdev
))
140 return drm_mode_config_helper_resume(&vbox
->ddev
);
143 static int vbox_pm_freeze(struct device
*dev
)
145 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
147 return drm_mode_config_helper_suspend(&vbox
->ddev
);
150 static int vbox_pm_thaw(struct device
*dev
)
152 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
154 return drm_mode_config_helper_resume(&vbox
->ddev
);
157 static int vbox_pm_poweroff(struct device
*dev
)
159 struct vbox_private
*vbox
= dev_get_drvdata(dev
);
161 return drm_mode_config_helper_suspend(&vbox
->ddev
);
164 static const struct dev_pm_ops vbox_pm_ops
= {
165 .suspend
= vbox_pm_suspend
,
166 .resume
= vbox_pm_resume
,
167 .freeze
= vbox_pm_freeze
,
168 .thaw
= vbox_pm_thaw
,
169 .poweroff
= vbox_pm_poweroff
,
170 .restore
= vbox_pm_resume
,
174 static struct pci_driver vbox_pci_driver
= {
176 .id_table
= pciidlist
,
177 .probe
= vbox_pci_probe
,
178 .remove
= vbox_pci_remove
,
179 #ifdef CONFIG_PM_SLEEP
180 .driver
.pm
= &vbox_pm_ops
,
184 DEFINE_DRM_GEM_FOPS(vbox_fops
);
186 static struct drm_driver driver
= {
188 DRIVER_MODESET
| DRIVER_GEM
| DRIVER_ATOMIC
,
190 .lastclose
= drm_fb_helper_lastclose
,
193 .irq_handler
= vbox_irq_handler
,
197 .major
= DRIVER_MAJOR
,
198 .minor
= DRIVER_MINOR
,
199 .patchlevel
= DRIVER_PATCHLEVEL
,
204 static int __init
vbox_init(void)
206 #ifdef CONFIG_VGA_CONSOLE
207 if (vgacon_text_force() && vbox_modeset
== -1)
211 if (vbox_modeset
== 0)
214 return pci_register_driver(&vbox_pci_driver
);
217 static void __exit
vbox_exit(void)
219 pci_unregister_driver(&vbox_pci_driver
);
222 module_init(vbox_init
);
223 module_exit(vbox_exit
);
225 MODULE_AUTHOR("Oracle Corporation");
226 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
227 MODULE_DESCRIPTION(DRIVER_DESC
);
228 MODULE_LICENSE("GPL and additional rights");