vbox_drv.c (4288B)
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/module.h> 11#include <linux/pci.h> 12#include <linux/vt_kern.h> 13 14#include <drm/drm_aperture.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> 21#include <drm/drm_module.h> 22 23#include "vbox_drv.h" 24 25static int vbox_modeset = -1; 26 27MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); 28module_param_named(modeset, vbox_modeset, int, 0400); 29 30static const struct drm_driver driver; 31 32static const struct pci_device_id pciidlist[] = { 33 { PCI_DEVICE(0x80ee, 0xbeef) }, 34 { } 35}; 36MODULE_DEVICE_TABLE(pci, pciidlist); 37 38static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 39{ 40 struct vbox_private *vbox; 41 int ret = 0; 42 43 if (!vbox_check_supported(VBE_DISPI_ID_HGSMI)) 44 return -ENODEV; 45 46 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &driver); 47 if (ret) 48 return ret; 49 50 vbox = devm_drm_dev_alloc(&pdev->dev, &driver, 51 struct vbox_private, ddev); 52 if (IS_ERR(vbox)) 53 return PTR_ERR(vbox); 54 55 pci_set_drvdata(pdev, vbox); 56 mutex_init(&vbox->hw_mutex); 57 58 ret = pcim_enable_device(pdev); 59 if (ret) 60 return ret; 61 62 ret = vbox_hw_init(vbox); 63 if (ret) 64 return ret; 65 66 ret = vbox_mm_init(vbox); 67 if (ret) 68 goto err_hw_fini; 69 70 ret = vbox_mode_init(vbox); 71 if (ret) 72 goto err_hw_fini; 73 74 ret = vbox_irq_init(vbox); 75 if (ret) 76 goto err_mode_fini; 77 78 ret = drm_dev_register(&vbox->ddev, 0); 79 if (ret) 80 goto err_irq_fini; 81 82 drm_fbdev_generic_setup(&vbox->ddev, 32); 83 84 return 0; 85 86err_irq_fini: 87 vbox_irq_fini(vbox); 88err_mode_fini: 89 vbox_mode_fini(vbox); 90err_hw_fini: 91 vbox_hw_fini(vbox); 92 return ret; 93} 94 95static void vbox_pci_remove(struct pci_dev *pdev) 96{ 97 struct vbox_private *vbox = pci_get_drvdata(pdev); 98 99 drm_dev_unregister(&vbox->ddev); 100 vbox_irq_fini(vbox); 101 vbox_mode_fini(vbox); 102 vbox_hw_fini(vbox); 103} 104 105#ifdef CONFIG_PM_SLEEP 106static int vbox_pm_suspend(struct device *dev) 107{ 108 struct vbox_private *vbox = dev_get_drvdata(dev); 109 struct pci_dev *pdev = to_pci_dev(dev); 110 int error; 111 112 error = drm_mode_config_helper_suspend(&vbox->ddev); 113 if (error) 114 return error; 115 116 pci_save_state(pdev); 117 pci_disable_device(pdev); 118 pci_set_power_state(pdev, PCI_D3hot); 119 120 return 0; 121} 122 123static int vbox_pm_resume(struct device *dev) 124{ 125 struct vbox_private *vbox = dev_get_drvdata(dev); 126 struct pci_dev *pdev = to_pci_dev(dev); 127 128 if (pci_enable_device(pdev)) 129 return -EIO; 130 131 return drm_mode_config_helper_resume(&vbox->ddev); 132} 133 134static int vbox_pm_freeze(struct device *dev) 135{ 136 struct vbox_private *vbox = dev_get_drvdata(dev); 137 138 return drm_mode_config_helper_suspend(&vbox->ddev); 139} 140 141static int vbox_pm_thaw(struct device *dev) 142{ 143 struct vbox_private *vbox = dev_get_drvdata(dev); 144 145 return drm_mode_config_helper_resume(&vbox->ddev); 146} 147 148static int vbox_pm_poweroff(struct device *dev) 149{ 150 struct vbox_private *vbox = dev_get_drvdata(dev); 151 152 return drm_mode_config_helper_suspend(&vbox->ddev); 153} 154 155static const struct dev_pm_ops vbox_pm_ops = { 156 .suspend = vbox_pm_suspend, 157 .resume = vbox_pm_resume, 158 .freeze = vbox_pm_freeze, 159 .thaw = vbox_pm_thaw, 160 .poweroff = vbox_pm_poweroff, 161 .restore = vbox_pm_resume, 162}; 163#endif 164 165static struct pci_driver vbox_pci_driver = { 166 .name = DRIVER_NAME, 167 .id_table = pciidlist, 168 .probe = vbox_pci_probe, 169 .remove = vbox_pci_remove, 170#ifdef CONFIG_PM_SLEEP 171 .driver.pm = &vbox_pm_ops, 172#endif 173}; 174 175DEFINE_DRM_GEM_FOPS(vbox_fops); 176 177static const struct drm_driver driver = { 178 .driver_features = 179 DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 180 181 .lastclose = drm_fb_helper_lastclose, 182 183 .fops = &vbox_fops, 184 .name = DRIVER_NAME, 185 .desc = DRIVER_DESC, 186 .date = DRIVER_DATE, 187 .major = DRIVER_MAJOR, 188 .minor = DRIVER_MINOR, 189 .patchlevel = DRIVER_PATCHLEVEL, 190 191 DRM_GEM_VRAM_DRIVER, 192}; 193 194drm_module_pci_driver_if_modeset(vbox_pci_driver, vbox_modeset); 195 196MODULE_AUTHOR("Oracle Corporation"); 197MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); 198MODULE_DESCRIPTION(DRIVER_DESC); 199MODULE_LICENSE("GPL and additional rights");