1f64122c1SDave Airlie /* vim: set ts=8 sw=8 tw=78 ai noexpandtab */ 2f64122c1SDave Airlie /* qxl_drv.c -- QXL driver -*- linux-c -*- 3f64122c1SDave Airlie * 4f64122c1SDave Airlie * Copyright 2011 Red Hat, Inc. 5f64122c1SDave Airlie * All Rights Reserved. 6f64122c1SDave Airlie * 7f64122c1SDave Airlie * Permission is hereby granted, free of charge, to any person obtaining a 8f64122c1SDave Airlie * copy of this software and associated documentation files (the "Software"), 9f64122c1SDave Airlie * to deal in the Software without restriction, including without limitation 10f64122c1SDave Airlie * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11f64122c1SDave Airlie * and/or sell copies of the Software, and to permit persons to whom the 12f64122c1SDave Airlie * Software is furnished to do so, subject to the following conditions: 13f64122c1SDave Airlie * 14f64122c1SDave Airlie * The above copyright notice and this permission notice (including the next 15f64122c1SDave Airlie * paragraph) shall be included in all copies or substantial portions of the 16f64122c1SDave Airlie * Software. 17f64122c1SDave Airlie * 18f64122c1SDave Airlie * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19f64122c1SDave Airlie * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20f64122c1SDave Airlie * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21f64122c1SDave Airlie * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22f64122c1SDave Airlie * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23f64122c1SDave Airlie * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24f64122c1SDave Airlie * OTHER DEALINGS IN THE SOFTWARE. 25f64122c1SDave Airlie * 26f64122c1SDave Airlie * Authors: 27f64122c1SDave Airlie * Dave Airlie <airlie@redhat.com> 28f64122c1SDave Airlie * Alon Levy <alevy@redhat.com> 29f64122c1SDave Airlie */ 30f64122c1SDave Airlie 31f64122c1SDave Airlie #include <linux/module.h> 32f64122c1SDave Airlie #include <linux/console.h> 33f64122c1SDave Airlie 34f64122c1SDave Airlie #include "drmP.h" 35f64122c1SDave Airlie #include "drm/drm.h" 36f64122c1SDave Airlie 37f64122c1SDave Airlie #include "qxl_drv.h" 38f64122c1SDave Airlie 39f64122c1SDave Airlie extern int qxl_max_ioctls; 40f64122c1SDave Airlie static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { 41f64122c1SDave Airlie { 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 42f64122c1SDave Airlie 0xffff00, 0 }, 43f64122c1SDave Airlie { 0x1b36, 0x100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_OTHER << 8, 44f64122c1SDave Airlie 0xffff00, 0 }, 45f64122c1SDave Airlie { 0, 0, 0 }, 46f64122c1SDave Airlie }; 47f64122c1SDave Airlie MODULE_DEVICE_TABLE(pci, pciidlist); 48f64122c1SDave Airlie 496d01f1f5SDave Airlie static int qxl_modeset = -1; 50*07f8d9bdSDave Airlie int qxl_num_crtc = 4; 51f64122c1SDave Airlie 52f64122c1SDave Airlie MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); 53f64122c1SDave Airlie module_param_named(modeset, qxl_modeset, int, 0400); 54f64122c1SDave Airlie 55*07f8d9bdSDave Airlie MODULE_PARM_DESC(num_heads, "Number of virtual crtcs to expose (default 4)"); 56*07f8d9bdSDave Airlie module_param_named(num_heads, qxl_num_crtc, int, 0400); 57*07f8d9bdSDave Airlie 58f64122c1SDave Airlie static struct drm_driver qxl_driver; 59f64122c1SDave Airlie static struct pci_driver qxl_pci_driver; 60f64122c1SDave Airlie 61f64122c1SDave Airlie static int 62f64122c1SDave Airlie qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 63f64122c1SDave Airlie { 64f64122c1SDave Airlie if (pdev->revision < 4) { 65f64122c1SDave Airlie DRM_ERROR("qxl too old, doesn't support client_monitors_config," 66f64122c1SDave Airlie " use xf86-video-qxl in user mode"); 67f64122c1SDave Airlie return -EINVAL; /* TODO: ENODEV ? */ 68f64122c1SDave Airlie } 69f64122c1SDave Airlie return drm_get_pci_dev(pdev, ent, &qxl_driver); 70f64122c1SDave Airlie } 71f64122c1SDave Airlie 72f64122c1SDave Airlie static void 73f64122c1SDave Airlie qxl_pci_remove(struct pci_dev *pdev) 74f64122c1SDave Airlie { 75f64122c1SDave Airlie struct drm_device *dev = pci_get_drvdata(pdev); 76f64122c1SDave Airlie 77f64122c1SDave Airlie drm_put_dev(dev); 78f64122c1SDave Airlie } 79f64122c1SDave Airlie 80f64122c1SDave Airlie static struct pci_driver qxl_pci_driver = { 81f64122c1SDave Airlie .name = DRIVER_NAME, 82f64122c1SDave Airlie .id_table = pciidlist, 83f64122c1SDave Airlie .probe = qxl_pci_probe, 84f64122c1SDave Airlie .remove = qxl_pci_remove, 85f64122c1SDave Airlie }; 86f64122c1SDave Airlie 87f64122c1SDave Airlie static const struct file_operations qxl_fops = { 88f64122c1SDave Airlie .owner = THIS_MODULE, 89f64122c1SDave Airlie .open = drm_open, 90f64122c1SDave Airlie .release = drm_release, 91f64122c1SDave Airlie .unlocked_ioctl = drm_ioctl, 92f64122c1SDave Airlie .poll = drm_poll, 93f64122c1SDave Airlie .fasync = drm_fasync, 94f64122c1SDave Airlie .mmap = qxl_mmap, 95f64122c1SDave Airlie }; 96f64122c1SDave Airlie 97f64122c1SDave Airlie static struct drm_driver qxl_driver = { 98f64122c1SDave Airlie .driver_features = DRIVER_GEM | DRIVER_MODESET | 99f64122c1SDave Airlie DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, 100f64122c1SDave Airlie .dev_priv_size = 0, 101f64122c1SDave Airlie .load = qxl_driver_load, 102f64122c1SDave Airlie .unload = qxl_driver_unload, 103f64122c1SDave Airlie 104f64122c1SDave Airlie .dumb_create = qxl_mode_dumb_create, 105f64122c1SDave Airlie .dumb_map_offset = qxl_mode_dumb_mmap, 106f64122c1SDave Airlie .dumb_destroy = qxl_mode_dumb_destroy, 107f64122c1SDave Airlie #if defined(CONFIG_DEBUG_FS) 108f64122c1SDave Airlie .debugfs_init = qxl_debugfs_init, 109f64122c1SDave Airlie .debugfs_cleanup = qxl_debugfs_takedown, 110f64122c1SDave Airlie #endif 111f64122c1SDave Airlie .gem_init_object = qxl_gem_object_init, 112f64122c1SDave Airlie .gem_free_object = qxl_gem_object_free, 113f64122c1SDave Airlie .gem_open_object = qxl_gem_object_open, 114f64122c1SDave Airlie .gem_close_object = qxl_gem_object_close, 115f64122c1SDave Airlie .fops = &qxl_fops, 116f64122c1SDave Airlie .ioctls = qxl_ioctls, 117f64122c1SDave Airlie .irq_handler = qxl_irq_handler, 118f64122c1SDave Airlie .name = DRIVER_NAME, 119f64122c1SDave Airlie .desc = DRIVER_DESC, 120f64122c1SDave Airlie .date = DRIVER_DATE, 121f64122c1SDave Airlie .major = 0, 122f64122c1SDave Airlie .minor = 1, 123f64122c1SDave Airlie .patchlevel = 0, 124f64122c1SDave Airlie }; 125f64122c1SDave Airlie 126f64122c1SDave Airlie static int __init qxl_init(void) 127f64122c1SDave Airlie { 128f64122c1SDave Airlie #ifdef CONFIG_VGA_CONSOLE 129f64122c1SDave Airlie if (vgacon_text_force() && qxl_modeset == -1) 130f64122c1SDave Airlie return -EINVAL; 131f64122c1SDave Airlie #endif 132f64122c1SDave Airlie 133f64122c1SDave Airlie if (qxl_modeset == 0) 134f64122c1SDave Airlie return -EINVAL; 135f64122c1SDave Airlie qxl_driver.num_ioctls = qxl_max_ioctls; 136f64122c1SDave Airlie return drm_pci_init(&qxl_driver, &qxl_pci_driver); 137f64122c1SDave Airlie } 138f64122c1SDave Airlie 139f64122c1SDave Airlie static void __exit qxl_exit(void) 140f64122c1SDave Airlie { 141f64122c1SDave Airlie drm_pci_exit(&qxl_driver, &qxl_pci_driver); 142f64122c1SDave Airlie } 143f64122c1SDave Airlie 144f64122c1SDave Airlie module_init(qxl_init); 145f64122c1SDave Airlie module_exit(qxl_exit); 146f64122c1SDave Airlie 147f64122c1SDave Airlie MODULE_AUTHOR(DRIVER_AUTHOR); 148f64122c1SDave Airlie MODULE_DESCRIPTION(DRIVER_DESC); 149f64122c1SDave Airlie MODULE_LICENSE("GPL and additional rights"); 150