Linus 5.3-rc1
[sfrench/cifs-2.6.git] / drivers / gpu / drm / vboxvideo / vbox_drv.c
1 // SPDX-License-Identifier: MIT
2 /*
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>
9  */
10 #include <linux/console.h>
11 #include <linux/module.h>
12 #include <linux/pci.h>
13 #include <linux/vt_kern.h>
14
15 #include <drm/drm_crtc_helper.h>
16 #include <drm/drm_drv.h>
17 #include <drm/drm_file.h>
18 #include <drm/drm_ioctl.h>
19
20 #include "vbox_drv.h"
21
22 static int vbox_modeset = -1;
23
24 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
25 module_param_named(modeset, vbox_modeset, int, 0400);
26
27 static struct drm_driver driver;
28
29 static const struct pci_device_id pciidlist[] = {
30         { PCI_DEVICE(0x80ee, 0xbeef) },
31         { }
32 };
33 MODULE_DEVICE_TABLE(pci, pciidlist);
34
35 static struct drm_fb_helper_funcs vbox_fb_helper_funcs = {
36         .fb_probe = vboxfb_create,
37 };
38
39 static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
40 {
41         struct vbox_private *vbox;
42         int ret = 0;
43
44         if (!vbox_check_supported(VBE_DISPI_ID_HGSMI))
45                 return -ENODEV;
46
47         vbox = kzalloc(sizeof(*vbox), GFP_KERNEL);
48         if (!vbox)
49                 return -ENOMEM;
50
51         ret = drm_dev_init(&vbox->ddev, &driver, &pdev->dev);
52         if (ret) {
53                 kfree(vbox);
54                 return ret;
55         }
56
57         vbox->ddev.pdev = pdev;
58         vbox->ddev.dev_private = vbox;
59         pci_set_drvdata(pdev, vbox);
60         mutex_init(&vbox->hw_mutex);
61
62         ret = pci_enable_device(pdev);
63         if (ret)
64                 goto err_dev_put;
65
66         ret = vbox_hw_init(vbox);
67         if (ret)
68                 goto err_pci_disable;
69
70         ret = vbox_mm_init(vbox);
71         if (ret)
72                 goto err_hw_fini;
73
74         ret = vbox_mode_init(vbox);
75         if (ret)
76                 goto err_mm_fini;
77
78         ret = vbox_irq_init(vbox);
79         if (ret)
80                 goto err_mode_fini;
81
82         ret = drm_fb_helper_fbdev_setup(&vbox->ddev, &vbox->fb_helper,
83                                         &vbox_fb_helper_funcs, 32,
84                                         vbox->num_crtcs);
85         if (ret)
86                 goto err_irq_fini;
87
88         ret = drm_dev_register(&vbox->ddev, 0);
89         if (ret)
90                 goto err_fbdev_fini;
91
92         return 0;
93
94 err_fbdev_fini:
95         vbox_fbdev_fini(vbox);
96 err_irq_fini:
97         vbox_irq_fini(vbox);
98 err_mode_fini:
99         vbox_mode_fini(vbox);
100 err_mm_fini:
101         vbox_mm_fini(vbox);
102 err_hw_fini:
103         vbox_hw_fini(vbox);
104 err_pci_disable:
105         pci_disable_device(pdev);
106 err_dev_put:
107         drm_dev_put(&vbox->ddev);
108         return ret;
109 }
110
111 static void vbox_pci_remove(struct pci_dev *pdev)
112 {
113         struct vbox_private *vbox = pci_get_drvdata(pdev);
114
115         drm_dev_unregister(&vbox->ddev);
116         vbox_fbdev_fini(vbox);
117         vbox_irq_fini(vbox);
118         vbox_mode_fini(vbox);
119         vbox_mm_fini(vbox);
120         vbox_hw_fini(vbox);
121         drm_dev_put(&vbox->ddev);
122 }
123
124 #ifdef CONFIG_PM_SLEEP
125 static int vbox_pm_suspend(struct device *dev)
126 {
127         struct vbox_private *vbox = dev_get_drvdata(dev);
128         int error;
129
130         error = drm_mode_config_helper_suspend(&vbox->ddev);
131         if (error)
132                 return error;
133
134         pci_save_state(vbox->ddev.pdev);
135         pci_disable_device(vbox->ddev.pdev);
136         pci_set_power_state(vbox->ddev.pdev, PCI_D3hot);
137
138         return 0;
139 }
140
141 static int vbox_pm_resume(struct device *dev)
142 {
143         struct vbox_private *vbox = dev_get_drvdata(dev);
144
145         if (pci_enable_device(vbox->ddev.pdev))
146                 return -EIO;
147
148         return drm_mode_config_helper_resume(&vbox->ddev);
149 }
150
151 static int vbox_pm_freeze(struct device *dev)
152 {
153         struct vbox_private *vbox = dev_get_drvdata(dev);
154
155         return drm_mode_config_helper_suspend(&vbox->ddev);
156 }
157
158 static int vbox_pm_thaw(struct device *dev)
159 {
160         struct vbox_private *vbox = dev_get_drvdata(dev);
161
162         return drm_mode_config_helper_resume(&vbox->ddev);
163 }
164
165 static int vbox_pm_poweroff(struct device *dev)
166 {
167         struct vbox_private *vbox = dev_get_drvdata(dev);
168
169         return drm_mode_config_helper_suspend(&vbox->ddev);
170 }
171
172 static const struct dev_pm_ops vbox_pm_ops = {
173         .suspend = vbox_pm_suspend,
174         .resume = vbox_pm_resume,
175         .freeze = vbox_pm_freeze,
176         .thaw = vbox_pm_thaw,
177         .poweroff = vbox_pm_poweroff,
178         .restore = vbox_pm_resume,
179 };
180 #endif
181
182 static struct pci_driver vbox_pci_driver = {
183         .name = DRIVER_NAME,
184         .id_table = pciidlist,
185         .probe = vbox_pci_probe,
186         .remove = vbox_pci_remove,
187 #ifdef CONFIG_PM_SLEEP
188         .driver.pm = &vbox_pm_ops,
189 #endif
190 };
191
192 static const struct file_operations vbox_fops = {
193         .owner = THIS_MODULE,
194         DRM_VRAM_MM_FILE_OPERATIONS
195 };
196
197 static struct drm_driver driver = {
198         .driver_features =
199             DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC,
200
201         .lastclose = drm_fb_helper_lastclose,
202
203         .fops = &vbox_fops,
204         .irq_handler = vbox_irq_handler,
205         .name = DRIVER_NAME,
206         .desc = DRIVER_DESC,
207         .date = DRIVER_DATE,
208         .major = DRIVER_MAJOR,
209         .minor = DRIVER_MINOR,
210         .patchlevel = DRIVER_PATCHLEVEL,
211
212         DRM_GEM_VRAM_DRIVER,
213         .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
214         .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
215         .gem_prime_export = drm_gem_prime_export,
216         .gem_prime_import = drm_gem_prime_import,
217         .gem_prime_pin = vbox_gem_prime_pin,
218         .gem_prime_unpin = vbox_gem_prime_unpin,
219         .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table,
220         .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table,
221         .gem_prime_vmap = vbox_gem_prime_vmap,
222         .gem_prime_vunmap = vbox_gem_prime_vunmap,
223         .gem_prime_mmap = vbox_gem_prime_mmap,
224 };
225
226 static int __init vbox_init(void)
227 {
228 #ifdef CONFIG_VGA_CONSOLE
229         if (vgacon_text_force() && vbox_modeset == -1)
230                 return -EINVAL;
231 #endif
232
233         if (vbox_modeset == 0)
234                 return -EINVAL;
235
236         return pci_register_driver(&vbox_pci_driver);
237 }
238
239 static void __exit vbox_exit(void)
240 {
241         pci_unregister_driver(&vbox_pci_driver);
242 }
243
244 module_init(vbox_init);
245 module_exit(vbox_exit);
246
247 MODULE_AUTHOR("Oracle Corporation");
248 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
249 MODULE_DESCRIPTION(DRIVER_DESC);
250 MODULE_LICENSE("GPL and additional rights");