]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/gpu/drm/bochs/bochs_drv.c
treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 152
[mirror_ubuntu-eoan-kernel.git] / drivers / gpu / drm / bochs / bochs_drv.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
0a6659bd 2/*
0a6659bd
GH
3 */
4
5#include <linux/mm.h>
6#include <linux/module.h>
7#include <linux/slab.h>
44adece5 8#include <drm/drm_fb_helper.h>
fcd70cd3 9#include <drm/drm_probe_helper.h>
0a6659bd
GH
10
11#include "bochs.h"
12
1acf5661
MS
13static int bochs_modeset = -1;
14module_param_named(modeset, bochs_modeset, int, 0444);
15MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
16
0a6659bd
GH
17/* ---------------------------------------------------------------------- */
18/* drm interface */
19
11b3c20b 20static void bochs_unload(struct drm_device *dev)
0a6659bd
GH
21{
22 struct bochs_device *bochs = dev->dev_private;
23
0a6659bd
GH
24 bochs_kms_fini(bochs);
25 bochs_mm_fini(bochs);
26 bochs_hw_fini(dev);
27 kfree(bochs);
28 dev->dev_private = NULL;
0a6659bd
GH
29}
30
7780eb9c 31static int bochs_load(struct drm_device *dev)
0a6659bd
GH
32{
33 struct bochs_device *bochs;
34 int ret;
35
36 bochs = kzalloc(sizeof(*bochs), GFP_KERNEL);
37 if (bochs == NULL)
38 return -ENOMEM;
39 dev->dev_private = bochs;
40 bochs->dev = dev;
41
7780eb9c 42 ret = bochs_hw_init(dev);
0a6659bd
GH
43 if (ret)
44 goto err;
45
46 ret = bochs_mm_init(bochs);
47 if (ret)
48 goto err;
49
50 ret = bochs_kms_init(bochs);
51 if (ret)
52 goto err;
53
0a6659bd
GH
54 return 0;
55
56err:
57 bochs_unload(dev);
58 return ret;
59}
60
61static const struct file_operations bochs_fops = {
62 .owner = THIS_MODULE,
63 .open = drm_open,
64 .release = drm_release,
65 .unlocked_ioctl = drm_ioctl,
0a6659bd 66 .compat_ioctl = drm_compat_ioctl,
0a6659bd
GH
67 .poll = drm_poll,
68 .read = drm_read,
69 .llseek = no_llseek,
70 .mmap = bochs_mmap,
71};
72
73static struct drm_driver bochs_driver = {
132a4534
GH
74 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC |
75 DRIVER_PRIME,
0a6659bd
GH
76 .fops = &bochs_fops,
77 .name = "bochs-drm",
78 .desc = "bochs dispi vga interface (qemu stdvga)",
79 .date = "20130925",
80 .major = 1,
81 .minor = 0,
6f2c1c15 82 .gem_free_object_unlocked = bochs_gem_free_object,
0a6659bd
GH
83 .dumb_create = bochs_dumb_create,
84 .dumb_map_offset = bochs_dumb_mmap_offset,
132a4534
GH
85
86 .gem_prime_export = drm_gem_prime_export,
87 .gem_prime_import = drm_gem_prime_import,
88 .gem_prime_pin = bochs_gem_prime_pin,
89 .gem_prime_unpin = bochs_gem_prime_unpin,
90 .gem_prime_vmap = bochs_gem_prime_vmap,
91 .gem_prime_vunmap = bochs_gem_prime_vunmap,
92 .gem_prime_mmap = bochs_gem_prime_mmap,
0a6659bd
GH
93};
94
b8ccd70f
GH
95/* ---------------------------------------------------------------------- */
96/* pm interface */
97
150cee9c 98#ifdef CONFIG_PM_SLEEP
b8ccd70f
GH
99static int bochs_pm_suspend(struct device *dev)
100{
101 struct pci_dev *pdev = to_pci_dev(dev);
102 struct drm_device *drm_dev = pci_get_drvdata(pdev);
b8ccd70f 103
568a4c72 104 return drm_mode_config_helper_suspend(drm_dev);
b8ccd70f
GH
105}
106
107static int bochs_pm_resume(struct device *dev)
108{
109 struct pci_dev *pdev = to_pci_dev(dev);
110 struct drm_device *drm_dev = pci_get_drvdata(pdev);
b8ccd70f 111
568a4c72 112 return drm_mode_config_helper_resume(drm_dev);
b8ccd70f 113}
150cee9c 114#endif
b8ccd70f
GH
115
116static const struct dev_pm_ops bochs_pm_ops = {
117 SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend,
118 bochs_pm_resume)
119};
120
0a6659bd
GH
121/* ---------------------------------------------------------------------- */
122/* pci interface */
123
0a6659bd
GH
124static int bochs_pci_probe(struct pci_dev *pdev,
125 const struct pci_device_id *ent)
126{
7780eb9c 127 struct drm_device *dev;
de595762 128 unsigned long fbsize;
0a6659bd
GH
129 int ret;
130
de595762
GH
131 fbsize = pci_resource_len(pdev, 0);
132 if (fbsize < 4 * 1024 * 1024) {
133 DRM_ERROR("less than 4 MB video memory, ignoring device\n");
134 return -ENOMEM;
135 }
136
77d1ed41 137 ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, 0, "bochsdrmfb");
0a6659bd
GH
138 if (ret)
139 return ret;
140
7780eb9c
PW
141 dev = drm_dev_alloc(&bochs_driver, &pdev->dev);
142 if (IS_ERR(dev))
143 return PTR_ERR(dev);
144
17fb465f
AF
145 ret = pci_enable_device(pdev);
146 if (ret)
147 goto err_free_dev;
148
7780eb9c
PW
149 dev->pdev = pdev;
150 pci_set_drvdata(pdev, dev);
151
152 ret = bochs_load(dev);
153 if (ret)
154 goto err_free_dev;
155
156 ret = drm_dev_register(dev, 0);
157 if (ret)
158 goto err_unload;
159
7a0483ac 160 drm_fbdev_generic_setup(dev, 32);
7780eb9c
PW
161 return ret;
162
163err_unload:
164 bochs_unload(dev);
165err_free_dev:
166 drm_dev_put(dev);
167 return ret;
0a6659bd
GH
168}
169
170static void bochs_pci_remove(struct pci_dev *pdev)
171{
172 struct drm_device *dev = pci_get_drvdata(pdev);
173
7780eb9c
PW
174 drm_dev_unregister(dev);
175 bochs_unload(dev);
176 drm_dev_put(dev);
0a6659bd
GH
177}
178
9baa3c34 179static const struct pci_device_id bochs_pci_tbl[] = {
0a6659bd
GH
180 {
181 .vendor = 0x1234,
182 .device = 0x1111,
caf02abf
RJ
183 .subvendor = PCI_SUBVENDOR_ID_REDHAT_QUMRANET,
184 .subdevice = PCI_SUBDEVICE_ID_QEMU,
0a6659bd
GH
185 .driver_data = BOCHS_QEMU_STDVGA,
186 },
187 {
188 .vendor = 0x1234,
189 .device = 0x1111,
190 .subvendor = PCI_ANY_ID,
191 .subdevice = PCI_ANY_ID,
192 .driver_data = BOCHS_UNKNOWN,
193 },
194 { /* end of list */ }
195};
196
197static struct pci_driver bochs_pci_driver = {
198 .name = "bochs-drm",
199 .id_table = bochs_pci_tbl,
200 .probe = bochs_pci_probe,
201 .remove = bochs_pci_remove,
b8ccd70f 202 .driver.pm = &bochs_pm_ops,
0a6659bd
GH
203};
204
205/* ---------------------------------------------------------------------- */
206/* module init/exit */
207
208static int __init bochs_init(void)
209{
1acf5661
MS
210 if (vgacon_text_force() && bochs_modeset == -1)
211 return -EINVAL;
212
213 if (bochs_modeset == 0)
214 return -EINVAL;
215
10631d72 216 return pci_register_driver(&bochs_pci_driver);
0a6659bd
GH
217}
218
219static void __exit bochs_exit(void)
220{
10631d72 221 pci_unregister_driver(&bochs_pci_driver);
0a6659bd
GH
222}
223
224module_init(bochs_init);
225module_exit(bochs_exit);
226
227MODULE_DEVICE_TABLE(pci, bochs_pci_tbl);
228MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
229MODULE_LICENSE("GPL");