linux/drivers/gpu/drm/cirrus/cirrus_drv.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Red Hat <mjg@redhat.com>
   3 *
   4 * This file is subject to the terms and conditions of the GNU General
   5 * Public License version 2. See the file COPYING in the main
   6 * directory of this archive for more details.
   7 *
   8 * Authors: Matthew Garrett
   9 *          Dave Airlie
  10 */
  11#include <linux/module.h>
  12#include <linux/console.h>
  13#include <drm/drmP.h>
  14#include <drm/drm_crtc_helper.h>
  15
  16#include "cirrus_drv.h"
  17
  18int cirrus_modeset = -1;
  19int cirrus_bpp = 24;
  20
  21MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
  22module_param_named(modeset, cirrus_modeset, int, 0400);
  23MODULE_PARM_DESC(bpp, "Max bits-per-pixel (default:24)");
  24module_param_named(bpp, cirrus_bpp, int, 0400);
  25
  26/*
  27 * This is the generic driver code. This binds the driver to the drm core,
  28 * which then performs further device association and calls our graphics init
  29 * functions
  30 */
  31
  32static struct drm_driver driver;
  33
  34/* only bind to the cirrus chip in qemu */
  35static const struct pci_device_id pciidlist[] = {
  36        { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
  37          0, 0 },
  38        { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, PCI_VENDOR_ID_XEN,
  39          0x0001, 0, 0, 0 },
  40        {0,}
  41};
  42
  43
  44static int cirrus_kick_out_firmware_fb(struct pci_dev *pdev)
  45{
  46        struct apertures_struct *ap;
  47        bool primary = false;
  48
  49        ap = alloc_apertures(1);
  50        if (!ap)
  51                return -ENOMEM;
  52
  53        ap->ranges[0].base = pci_resource_start(pdev, 0);
  54        ap->ranges[0].size = pci_resource_len(pdev, 0);
  55
  56#ifdef CONFIG_X86
  57        primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
  58#endif
  59        remove_conflicting_framebuffers(ap, "cirrusdrmfb", primary);
  60        kfree(ap);
  61
  62        return 0;
  63}
  64
  65static int cirrus_pci_probe(struct pci_dev *pdev,
  66                            const struct pci_device_id *ent)
  67{
  68        int ret;
  69
  70        ret = cirrus_kick_out_firmware_fb(pdev);
  71        if (ret)
  72                return ret;
  73
  74        return drm_get_pci_dev(pdev, ent, &driver);
  75}
  76
  77static void cirrus_pci_remove(struct pci_dev *pdev)
  78{
  79        struct drm_device *dev = pci_get_drvdata(pdev);
  80
  81        drm_put_dev(dev);
  82}
  83
  84#ifdef CONFIG_PM_SLEEP
  85static int cirrus_pm_suspend(struct device *dev)
  86{
  87        struct pci_dev *pdev = to_pci_dev(dev);
  88        struct drm_device *drm_dev = pci_get_drvdata(pdev);
  89        struct cirrus_device *cdev = drm_dev->dev_private;
  90
  91        drm_kms_helper_poll_disable(drm_dev);
  92
  93        if (cdev->mode_info.gfbdev) {
  94                console_lock();
  95                fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1);
  96                console_unlock();
  97        }
  98
  99        return 0;
 100}
 101
 102static int cirrus_pm_resume(struct device *dev)
 103{
 104        struct pci_dev *pdev = to_pci_dev(dev);
 105        struct drm_device *drm_dev = pci_get_drvdata(pdev);
 106        struct cirrus_device *cdev = drm_dev->dev_private;
 107
 108        drm_helper_resume_force_mode(drm_dev);
 109
 110        if (cdev->mode_info.gfbdev) {
 111                console_lock();
 112                fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0);
 113                console_unlock();
 114        }
 115
 116        drm_kms_helper_poll_enable(drm_dev);
 117        return 0;
 118}
 119#endif
 120
 121static const struct file_operations cirrus_driver_fops = {
 122        .owner = THIS_MODULE,
 123        .open = drm_open,
 124        .release = drm_release,
 125        .unlocked_ioctl = drm_ioctl,
 126        .mmap = cirrus_mmap,
 127        .poll = drm_poll,
 128#ifdef CONFIG_COMPAT
 129        .compat_ioctl = drm_compat_ioctl,
 130#endif
 131};
 132static struct drm_driver driver = {
 133        .driver_features = DRIVER_MODESET | DRIVER_GEM,
 134        .load = cirrus_driver_load,
 135        .unload = cirrus_driver_unload,
 136        .set_busid = drm_pci_set_busid,
 137        .fops = &cirrus_driver_fops,
 138        .name = DRIVER_NAME,
 139        .desc = DRIVER_DESC,
 140        .date = DRIVER_DATE,
 141        .major = DRIVER_MAJOR,
 142        .minor = DRIVER_MINOR,
 143        .patchlevel = DRIVER_PATCHLEVEL,
 144        .gem_free_object = cirrus_gem_free_object,
 145        .dumb_create = cirrus_dumb_create,
 146        .dumb_map_offset = cirrus_dumb_mmap_offset,
 147        .dumb_destroy = drm_gem_dumb_destroy,
 148};
 149
 150static const struct dev_pm_ops cirrus_pm_ops = {
 151        SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend,
 152                                cirrus_pm_resume)
 153};
 154
 155static struct pci_driver cirrus_pci_driver = {
 156        .name = DRIVER_NAME,
 157        .id_table = pciidlist,
 158        .probe = cirrus_pci_probe,
 159        .remove = cirrus_pci_remove,
 160        .driver.pm = &cirrus_pm_ops,
 161};
 162
 163static int __init cirrus_init(void)
 164{
 165#ifdef CONFIG_VGA_CONSOLE
 166        if (vgacon_text_force() && cirrus_modeset == -1)
 167                return -EINVAL;
 168#endif
 169
 170        if (cirrus_modeset == 0)
 171                return -EINVAL;
 172        return drm_pci_init(&driver, &cirrus_pci_driver);
 173}
 174
 175static void __exit cirrus_exit(void)
 176{
 177        drm_pci_exit(&driver, &cirrus_pci_driver);
 178}
 179
 180module_init(cirrus_init);
 181module_exit(cirrus_exit);
 182
 183MODULE_DEVICE_TABLE(pci, pciidlist);
 184MODULE_AUTHOR(DRIVER_AUTHOR);
 185MODULE_DESCRIPTION(DRIVER_DESC);
 186MODULE_LICENSE("GPL");
 187
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.