0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include <linux/module.h>
0030 #include <linux/pci.h>
0031 #include <linux/poll.h>
0032 #include <linux/wait.h>
0033
0034 #include <drm/drm.h>
0035 #include <drm/drm_aperture.h>
0036 #include <drm/drm_atomic_helper.h>
0037 #include <drm/drm_drv.h>
0038 #include <drm/drm_file.h>
0039
0040 #include "virtgpu_drv.h"
0041
0042 static const struct drm_driver driver;
0043
0044 static int virtio_gpu_modeset = -1;
0045
0046 MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
0047 module_param_named(modeset, virtio_gpu_modeset, int, 0400);
0048
0049 static int virtio_gpu_pci_quirk(struct drm_device *dev, struct virtio_device *vdev)
0050 {
0051 struct pci_dev *pdev = to_pci_dev(vdev->dev.parent);
0052 const char *pname = dev_name(&pdev->dev);
0053 bool vga = (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
0054 char unique[20];
0055 int ret;
0056
0057 DRM_INFO("pci: %s detected at %s\n",
0058 vga ? "virtio-vga" : "virtio-gpu-pci",
0059 pname);
0060 if (vga) {
0061 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver);
0062 if (ret)
0063 return ret;
0064 }
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 snprintf(unique, sizeof(unique), "pci:%s", pname);
0098 return drm_dev_set_unique(dev, unique);
0099 }
0100
0101 static int virtio_gpu_probe(struct virtio_device *vdev)
0102 {
0103 struct drm_device *dev;
0104 int ret;
0105
0106 if (drm_firmware_drivers_only() && virtio_gpu_modeset == -1)
0107 return -EINVAL;
0108
0109 if (virtio_gpu_modeset == 0)
0110 return -EINVAL;
0111
0112 dev = drm_dev_alloc(&driver, &vdev->dev);
0113 if (IS_ERR(dev))
0114 return PTR_ERR(dev);
0115 vdev->priv = dev;
0116
0117 if (!strcmp(vdev->dev.parent->bus->name, "pci")) {
0118 ret = virtio_gpu_pci_quirk(dev, vdev);
0119 if (ret)
0120 goto err_free;
0121 }
0122
0123 ret = virtio_gpu_init(dev);
0124 if (ret)
0125 goto err_free;
0126
0127 ret = drm_dev_register(dev, 0);
0128 if (ret)
0129 goto err_deinit;
0130
0131 drm_fbdev_generic_setup(vdev->priv, 32);
0132 return 0;
0133
0134 err_deinit:
0135 virtio_gpu_deinit(dev);
0136 err_free:
0137 drm_dev_put(dev);
0138 return ret;
0139 }
0140
0141 static void virtio_gpu_remove(struct virtio_device *vdev)
0142 {
0143 struct drm_device *dev = vdev->priv;
0144
0145 drm_dev_unplug(dev);
0146 drm_atomic_helper_shutdown(dev);
0147 virtio_gpu_deinit(dev);
0148 drm_dev_put(dev);
0149 }
0150
0151 static void virtio_gpu_config_changed(struct virtio_device *vdev)
0152 {
0153 struct drm_device *dev = vdev->priv;
0154 struct virtio_gpu_device *vgdev = dev->dev_private;
0155
0156 schedule_work(&vgdev->config_changed_work);
0157 }
0158
0159 static struct virtio_device_id id_table[] = {
0160 { VIRTIO_ID_GPU, VIRTIO_DEV_ANY_ID },
0161 { 0 },
0162 };
0163
0164 static unsigned int features[] = {
0165 #ifdef __LITTLE_ENDIAN
0166
0167
0168
0169
0170
0171 VIRTIO_GPU_F_VIRGL,
0172 #endif
0173 VIRTIO_GPU_F_EDID,
0174 VIRTIO_GPU_F_RESOURCE_UUID,
0175 VIRTIO_GPU_F_RESOURCE_BLOB,
0176 VIRTIO_GPU_F_CONTEXT_INIT,
0177 };
0178 static struct virtio_driver virtio_gpu_driver = {
0179 .feature_table = features,
0180 .feature_table_size = ARRAY_SIZE(features),
0181 .driver.name = KBUILD_MODNAME,
0182 .driver.owner = THIS_MODULE,
0183 .id_table = id_table,
0184 .probe = virtio_gpu_probe,
0185 .remove = virtio_gpu_remove,
0186 .config_changed = virtio_gpu_config_changed
0187 };
0188
0189 module_virtio_driver(virtio_gpu_driver);
0190
0191 MODULE_DEVICE_TABLE(virtio, id_table);
0192 MODULE_DESCRIPTION("Virtio GPU driver");
0193 MODULE_LICENSE("GPL and additional rights");
0194 MODULE_AUTHOR("Dave Airlie <airlied@redhat.com>");
0195 MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
0196 MODULE_AUTHOR("Alon Levy");
0197
0198 DEFINE_DRM_GEM_FOPS(virtio_gpu_driver_fops);
0199
0200 static const struct drm_driver driver = {
0201 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC,
0202 .open = virtio_gpu_driver_open,
0203 .postclose = virtio_gpu_driver_postclose,
0204
0205 .dumb_create = virtio_gpu_mode_dumb_create,
0206 .dumb_map_offset = virtio_gpu_mode_dumb_mmap,
0207
0208 #if defined(CONFIG_DEBUG_FS)
0209 .debugfs_init = virtio_gpu_debugfs_init,
0210 #endif
0211 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
0212 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
0213 .gem_prime_mmap = drm_gem_prime_mmap,
0214 .gem_prime_import = virtgpu_gem_prime_import,
0215 .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
0216
0217 .gem_create_object = virtio_gpu_create_object,
0218 .fops = &virtio_gpu_driver_fops,
0219
0220 .ioctls = virtio_gpu_ioctls,
0221 .num_ioctls = DRM_VIRTIO_NUM_IOCTLS,
0222
0223 .name = DRIVER_NAME,
0224 .desc = DRIVER_DESC,
0225 .date = DRIVER_DATE,
0226 .major = DRIVER_MAJOR,
0227 .minor = DRIVER_MINOR,
0228 .patchlevel = DRIVER_PATCHLEVEL,
0229
0230 .release = virtio_gpu_release,
0231 };