Chapter 2. DRM Internals

Table of Contents

Driver initialization
Driver load
Driver private & performance counters
Configuring the device
Memory manager initialization
Output configuration
VBlank event handling
Memory management
The Translation Table Manager (TTM)
The Graphics Execution Manager (GEM)
Output management
Framebuffer management
Command submission & fencing
Suspend/resume
DMA services

This chapter documents DRM internals relevant to driver authors and developers working to add support for the latest features to existing drivers.

First, we'll go over some typical driver initialization requirements, like setting up command buffers, creating an initial output configuration, and initializing core services. Subsequent sections will cover core internals in more detail, providing implementation notes and examples.

The DRM layer provides several services to graphics drivers, many of them driven by the application interfaces it provides through libdrm, the library that wraps most of the DRM ioctls. These include vblank event handling, memory management, output management, framebuffer management, command submission & fencing, suspend/resume support, and DMA services.

The core of every DRM driver is struct drm_driver. Drivers will typically statically initialize a drm_driver structure, then pass it to drm_init() at load time.

Driver initialization

Before calling the DRM initialization routines, the driver must first create and fill out a struct drm_driver structure.

      static struct drm_driver driver = {
	/* don't use mtrr's here, the Xserver or user space app should
	 * deal with them for intel hardware.
	 */
	.driver_features =
	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
	    DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_MODESET,
	.load = i915_driver_load,
	.unload = i915_driver_unload,
	.firstopen = i915_driver_firstopen,
	.lastclose = i915_driver_lastclose,
	.preclose = i915_driver_preclose,
	.save = i915_save,
	.restore = i915_restore,
	.device_is_agp = i915_driver_device_is_agp,
	.get_vblank_counter = i915_get_vblank_counter,
	.enable_vblank = i915_enable_vblank,
	.disable_vblank = i915_disable_vblank,
	.irq_preinstall = i915_driver_irq_preinstall,
	.irq_postinstall = i915_driver_irq_postinstall,
	.irq_uninstall = i915_driver_irq_uninstall,
	.irq_handler = i915_driver_irq_handler,
	.reclaim_buffers = drm_core_reclaim_buffers,
	.get_map_ofs = drm_core_get_map_ofs,
	.get_reg_ofs = drm_core_get_reg_ofs,
	.fb_probe = intelfb_probe,
	.fb_remove = intelfb_remove,
	.fb_resize = intelfb_resize,
	.master_create = i915_master_create,
	.master_destroy = i915_master_destroy,
#if defined(CONFIG_DEBUG_FS)
	.debugfs_init = i915_debugfs_init,
	.debugfs_cleanup = i915_debugfs_cleanup,
#endif
	.gem_init_object = i915_gem_init_object,
	.gem_free_object = i915_gem_free_object,
	.gem_vm_ops = &i915_gem_vm_ops,
	.ioctls = i915_ioctls,
	.fops = {
		.owner = THIS_MODULE,
		.open = drm_open,
		.release = drm_release,
		.ioctl = drm_ioctl,
		.mmap = drm_mmap,
		.poll = drm_poll,
		.fasync = drm_fasync,
#ifdef CONFIG_COMPAT
		.compat_ioctl = i915_compat_ioctl,
#endif
		.llseek = noop_llseek,
		},
	.pci_driver = {
		.name = DRIVER_NAME,
		.id_table = pciidlist,
		.probe = probe,
		.remove = __devexit_p(drm_cleanup_pci),
		},
	.name = DRIVER_NAME,
	.desc = DRIVER_DESC,
	.date = DRIVER_DATE,
	.major = DRIVER_MAJOR,
	.minor = DRIVER_MINOR,
	.patchlevel = DRIVER_PATCHLEVEL,
      };
    

In the example above, taken from the i915 DRM driver, the driver sets several flags indicating what core features it supports. We'll go over the individual callbacks in later sections. Since flags indicate which features your driver supports to the DRM core, you need to set most of them prior to calling drm_init(). Some, like DRIVER_MODESET can be set later based on user supplied parameters, but that's the exception rather than the rule.

Driver flags

DRIVER_USE_AGP

Driver uses AGP interface

DRIVER_REQUIRE_AGP

Driver needs AGP interface to function.

DRIVER_USE_MTRR

Driver uses MTRR interface for mapping memory. Deprecated.

DRIVER_PCI_DMA

Driver is capable of PCI DMA. Deprecated.

DRIVER_SG

Driver can perform scatter/gather DMA. Deprecated.

DRIVER_HAVE_DMA

Driver supports DMA. Deprecated.

DRIVER_HAVE_IRQ, DRIVER_IRQ_SHARED

DRIVER_HAVE_IRQ indicates whether the driver has a IRQ handler, DRIVER_IRQ_SHARED indicates whether the device & handler support shared IRQs (note that this is required of PCI drivers).

DRIVER_DMA_QUEUE

If the driver queues DMA requests and completes them asynchronously, this flag should be set. Deprecated.

DRIVER_FB_DMA

Driver supports DMA to/from the framebuffer. Deprecated.

DRIVER_MODESET

Driver supports mode setting interfaces.

In this specific case, the driver requires AGP and supports IRQs. DMA, as we'll see, is handled by device specific ioctls in this case. It also supports the kernel mode setting APIs, though unlike in the actual i915 driver source, this example unconditionally exports KMS capability.