linux/drivers/gpu/drm/vboxvideo/vbox_drv.c
<<
>>
Prefs
   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");
 200