1 1.1 riastrad /* $NetBSD: vbox_drv.c,v 1.2 2021/12/18 23:45:44 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* 5 1.1 riastrad * Copyright (C) 2013-2017 Oracle Corporation 6 1.1 riastrad * This file is based on ast_drv.c 7 1.1 riastrad * Copyright 2012 Red Hat Inc. 8 1.1 riastrad * Authors: Dave Airlie <airlied (at) redhat.com> 9 1.1 riastrad * Michael Thayer <michael.thayer (at) oracle.com, 10 1.1 riastrad * Hans de Goede <hdegoede (at) redhat.com> 11 1.1 riastrad */ 12 1.1 riastrad #include <sys/cdefs.h> 13 1.1 riastrad __KERNEL_RCSID(0, "$NetBSD: vbox_drv.c,v 1.2 2021/12/18 23:45:44 riastradh Exp $"); 14 1.1 riastrad 15 1.1 riastrad #include <linux/console.h> 16 1.1 riastrad #include <linux/module.h> 17 1.1 riastrad #include <linux/pci.h> 18 1.1 riastrad #include <linux/vt_kern.h> 19 1.1 riastrad 20 1.1 riastrad #include <drm/drm_crtc_helper.h> 21 1.1 riastrad #include <drm/drm_drv.h> 22 1.1 riastrad #include <drm/drm_fb_helper.h> 23 1.1 riastrad #include <drm/drm_file.h> 24 1.1 riastrad #include <drm/drm_ioctl.h> 25 1.1 riastrad 26 1.1 riastrad #include "vbox_drv.h" 27 1.1 riastrad 28 1.1 riastrad static int vbox_modeset = -1; 29 1.1 riastrad 30 1.1 riastrad MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); 31 1.1 riastrad module_param_named(modeset, vbox_modeset, int, 0400); 32 1.1 riastrad 33 1.1 riastrad static struct drm_driver driver; 34 1.1 riastrad 35 1.1 riastrad static const struct pci_device_id pciidlist[] = { 36 1.1 riastrad { PCI_DEVICE(0x80ee, 0xbeef) }, 37 1.1 riastrad { } 38 1.1 riastrad }; 39 1.1 riastrad MODULE_DEVICE_TABLE(pci, pciidlist); 40 1.1 riastrad 41 1.1 riastrad static int vbox_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 42 1.1 riastrad { 43 1.1 riastrad struct vbox_private *vbox; 44 1.1 riastrad int ret = 0; 45 1.1 riastrad 46 1.1 riastrad if (!vbox_check_supported(VBE_DISPI_ID_HGSMI)) 47 1.1 riastrad return -ENODEV; 48 1.1 riastrad 49 1.1 riastrad vbox = kzalloc(sizeof(*vbox), GFP_KERNEL); 50 1.1 riastrad if (!vbox) 51 1.1 riastrad return -ENOMEM; 52 1.1 riastrad 53 1.1 riastrad ret = drm_dev_init(&vbox->ddev, &driver, &pdev->dev); 54 1.1 riastrad if (ret) { 55 1.1 riastrad kfree(vbox); 56 1.1 riastrad return ret; 57 1.1 riastrad } 58 1.1 riastrad 59 1.1 riastrad vbox->ddev.pdev = pdev; 60 1.1 riastrad vbox->ddev.dev_private = vbox; 61 1.1 riastrad pci_set_drvdata(pdev, vbox); 62 1.1 riastrad mutex_init(&vbox->hw_mutex); 63 1.1 riastrad 64 1.1 riastrad ret = pci_enable_device(pdev); 65 1.1 riastrad if (ret) 66 1.1 riastrad goto err_dev_put; 67 1.1 riastrad 68 1.1 riastrad ret = vbox_hw_init(vbox); 69 1.1 riastrad if (ret) 70 1.1 riastrad goto err_pci_disable; 71 1.1 riastrad 72 1.1 riastrad ret = vbox_mm_init(vbox); 73 1.1 riastrad if (ret) 74 1.1 riastrad goto err_hw_fini; 75 1.1 riastrad 76 1.1 riastrad ret = vbox_mode_init(vbox); 77 1.1 riastrad if (ret) 78 1.1 riastrad goto err_mm_fini; 79 1.1 riastrad 80 1.1 riastrad ret = vbox_irq_init(vbox); 81 1.1 riastrad if (ret) 82 1.1 riastrad goto err_mode_fini; 83 1.1 riastrad 84 1.1 riastrad ret = drm_fbdev_generic_setup(&vbox->ddev, 32); 85 1.1 riastrad if (ret) 86 1.1 riastrad goto err_irq_fini; 87 1.1 riastrad 88 1.1 riastrad ret = drm_dev_register(&vbox->ddev, 0); 89 1.1 riastrad if (ret) 90 1.1 riastrad goto err_irq_fini; 91 1.1 riastrad 92 1.1 riastrad return 0; 93 1.1 riastrad 94 1.1 riastrad err_irq_fini: 95 1.1 riastrad vbox_irq_fini(vbox); 96 1.1 riastrad err_mode_fini: 97 1.1 riastrad vbox_mode_fini(vbox); 98 1.1 riastrad err_mm_fini: 99 1.1 riastrad vbox_mm_fini(vbox); 100 1.1 riastrad err_hw_fini: 101 1.1 riastrad vbox_hw_fini(vbox); 102 1.1 riastrad err_pci_disable: 103 1.1 riastrad pci_disable_device(pdev); 104 1.1 riastrad err_dev_put: 105 1.1 riastrad drm_dev_put(&vbox->ddev); 106 1.1 riastrad return ret; 107 1.1 riastrad } 108 1.1 riastrad 109 1.1 riastrad static void vbox_pci_remove(struct pci_dev *pdev) 110 1.1 riastrad { 111 1.1 riastrad struct vbox_private *vbox = pci_get_drvdata(pdev); 112 1.1 riastrad 113 1.1 riastrad drm_dev_unregister(&vbox->ddev); 114 1.1 riastrad vbox_irq_fini(vbox); 115 1.1 riastrad vbox_mode_fini(vbox); 116 1.1 riastrad vbox_mm_fini(vbox); 117 1.1 riastrad vbox_hw_fini(vbox); 118 1.1 riastrad drm_dev_put(&vbox->ddev); 119 1.1 riastrad } 120 1.1 riastrad 121 1.1 riastrad #ifdef CONFIG_PM_SLEEP 122 1.1 riastrad static int vbox_pm_suspend(struct device *dev) 123 1.1 riastrad { 124 1.1 riastrad struct vbox_private *vbox = dev_get_drvdata(dev); 125 1.1 riastrad int error; 126 1.1 riastrad 127 1.1 riastrad error = drm_mode_config_helper_suspend(&vbox->ddev); 128 1.1 riastrad if (error) 129 1.1 riastrad return error; 130 1.1 riastrad 131 1.1 riastrad pci_save_state(vbox->ddev.pdev); 132 1.1 riastrad pci_disable_device(vbox->ddev.pdev); 133 1.1 riastrad pci_set_power_state(vbox->ddev.pdev, PCI_D3hot); 134 1.1 riastrad 135 1.1 riastrad return 0; 136 1.1 riastrad } 137 1.1 riastrad 138 1.1 riastrad static int vbox_pm_resume(struct device *dev) 139 1.1 riastrad { 140 1.1 riastrad struct vbox_private *vbox = dev_get_drvdata(dev); 141 1.1 riastrad 142 1.1 riastrad if (pci_enable_device(vbox->ddev.pdev)) 143 1.1 riastrad return -EIO; 144 1.1 riastrad 145 1.1 riastrad return drm_mode_config_helper_resume(&vbox->ddev); 146 1.1 riastrad } 147 1.1 riastrad 148 1.1 riastrad static int vbox_pm_freeze(struct device *dev) 149 1.1 riastrad { 150 1.1 riastrad struct vbox_private *vbox = dev_get_drvdata(dev); 151 1.1 riastrad 152 1.1 riastrad return drm_mode_config_helper_suspend(&vbox->ddev); 153 1.1 riastrad } 154 1.1 riastrad 155 1.1 riastrad static int vbox_pm_thaw(struct device *dev) 156 1.1 riastrad { 157 1.1 riastrad struct vbox_private *vbox = dev_get_drvdata(dev); 158 1.1 riastrad 159 1.1 riastrad return drm_mode_config_helper_resume(&vbox->ddev); 160 1.1 riastrad } 161 1.1 riastrad 162 1.1 riastrad static int vbox_pm_poweroff(struct device *dev) 163 1.1 riastrad { 164 1.1 riastrad struct vbox_private *vbox = dev_get_drvdata(dev); 165 1.1 riastrad 166 1.1 riastrad return drm_mode_config_helper_suspend(&vbox->ddev); 167 1.1 riastrad } 168 1.1 riastrad 169 1.1 riastrad static const struct dev_pm_ops vbox_pm_ops = { 170 1.1 riastrad .suspend = vbox_pm_suspend, 171 1.1 riastrad .resume = vbox_pm_resume, 172 1.1 riastrad .freeze = vbox_pm_freeze, 173 1.1 riastrad .thaw = vbox_pm_thaw, 174 1.1 riastrad .poweroff = vbox_pm_poweroff, 175 1.1 riastrad .restore = vbox_pm_resume, 176 1.1 riastrad }; 177 1.1 riastrad #endif 178 1.1 riastrad 179 1.1 riastrad static struct pci_driver vbox_pci_driver = { 180 1.1 riastrad .name = DRIVER_NAME, 181 1.1 riastrad .id_table = pciidlist, 182 1.1 riastrad .probe = vbox_pci_probe, 183 1.1 riastrad .remove = vbox_pci_remove, 184 1.1 riastrad #ifdef CONFIG_PM_SLEEP 185 1.1 riastrad .driver.pm = &vbox_pm_ops, 186 1.1 riastrad #endif 187 1.1 riastrad }; 188 1.1 riastrad 189 1.1 riastrad DEFINE_DRM_GEM_FOPS(vbox_fops); 190 1.1 riastrad 191 1.1 riastrad static struct drm_driver driver = { 192 1.1 riastrad .driver_features = 193 1.1 riastrad DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 194 1.1 riastrad 195 1.1 riastrad .lastclose = drm_fb_helper_lastclose, 196 1.1 riastrad 197 1.1 riastrad .fops = &vbox_fops, 198 1.1 riastrad .irq_handler = vbox_irq_handler, 199 1.1 riastrad .name = DRIVER_NAME, 200 1.1 riastrad .desc = DRIVER_DESC, 201 1.1 riastrad .date = DRIVER_DATE, 202 1.1 riastrad .major = DRIVER_MAJOR, 203 1.1 riastrad .minor = DRIVER_MINOR, 204 1.1 riastrad .patchlevel = DRIVER_PATCHLEVEL, 205 1.1 riastrad 206 1.1 riastrad DRM_GEM_VRAM_DRIVER, 207 1.1 riastrad }; 208 1.1 riastrad 209 1.1 riastrad static int __init vbox_init(void) 210 1.1 riastrad { 211 1.1 riastrad #ifdef CONFIG_VGA_CONSOLE 212 1.1 riastrad if (vgacon_text_force() && vbox_modeset == -1) 213 1.1 riastrad return -EINVAL; 214 1.1 riastrad #endif 215 1.1 riastrad 216 1.1 riastrad if (vbox_modeset == 0) 217 1.1 riastrad return -EINVAL; 218 1.1 riastrad 219 1.1 riastrad return pci_register_driver(&vbox_pci_driver); 220 1.1 riastrad } 221 1.1 riastrad 222 1.1 riastrad static void __exit vbox_exit(void) 223 1.1 riastrad { 224 1.1 riastrad pci_unregister_driver(&vbox_pci_driver); 225 1.1 riastrad } 226 1.1 riastrad 227 1.1 riastrad module_init(vbox_init); 228 1.1 riastrad module_exit(vbox_exit); 229 1.1 riastrad 230 1.1 riastrad MODULE_AUTHOR("Oracle Corporation"); 231 1.1 riastrad MODULE_AUTHOR("Hans de Goede <hdegoede (at) redhat.com>"); 232 1.1 riastrad MODULE_DESCRIPTION(DRIVER_DESC); 233 1.1 riastrad MODULE_LICENSE("GPL and additional rights"); 234