123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- =============
- DRM Internals
- =============
- This chapter documents DRM internals relevant to driver authors and
- developers working to add support for the latest features to existing
- drivers.
- First, we go over some typical driver initialization requirements, like
- setting up command buffers, creating an initial output configuration,
- and initializing core services. Subsequent sections 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.
- Driver Initialization
- =====================
- At the core of every DRM driver is a :c:type:`struct drm_driver
- <drm_driver>` structure. Drivers typically statically initialize
- a drm_driver structure, and then pass it to
- :c:func:`drm_dev_alloc()` to allocate a device instance. After the
- device instance is fully initialized it can be registered (which makes
- it accessible from userspace) using :c:func:`drm_dev_register()`.
- The :c:type:`struct drm_driver <drm_driver>` structure
- contains static information that describes the driver and features it
- supports, and pointers to methods that the DRM core will call to
- implement the DRM API. We will first go through the :c:type:`struct
- drm_driver <drm_driver>` static information fields, and will
- then describe individual operations in details as they get used in later
- sections.
- Driver Information
- ------------------
- Driver Features
- ~~~~~~~~~~~~~~~
- Drivers inform the DRM core about their requirements and supported
- features by setting appropriate flags in the driver_features field.
- Since those flags influence the DRM core behaviour since registration
- time, most of them must be set to registering the :c:type:`struct
- drm_driver <drm_driver>` instance.
- u32 driver_features;
- DRIVER_USE_AGP
- Driver uses AGP interface, the DRM core will manage AGP resources.
- DRIVER_LEGACY
- Denote a legacy driver using shadow attach. Don't use.
- DRIVER_KMS_LEGACY_CONTEXT
- Used only by nouveau for backwards compatibility with existing userspace.
- Don't use.
- DRIVER_PCI_DMA
- Driver is capable of PCI DMA, mapping of PCI DMA buffers to
- userspace will be enabled. Deprecated.
- DRIVER_SG
- Driver can perform scatter/gather DMA, allocation and mapping of
- scatter/gather buffers will be enabled. Deprecated.
- DRIVER_HAVE_DMA
- Driver supports DMA, the userspace DMA API will be supported.
- Deprecated.
- DRIVER_HAVE_IRQ; DRIVER_IRQ_SHARED
- DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler
- managed by the DRM Core. The core will support simple IRQ handler
- installation when the flag is set. The installation process is
- described in ?.
- DRIVER_IRQ_SHARED indicates whether the device & handler support
- shared IRQs (note that this is required of PCI drivers).
- DRIVER_GEM
- Driver use the GEM memory manager.
- DRIVER_MODESET
- Driver supports mode setting interfaces (KMS).
- DRIVER_PRIME
- Driver implements DRM PRIME buffer sharing.
- DRIVER_RENDER
- Driver supports dedicated render nodes.
- DRIVER_ATOMIC
- Driver supports atomic properties. In this case the driver must
- implement appropriate obj->atomic_get_property() vfuncs for any
- modeset objects with driver specific properties.
- Major, Minor and Patchlevel
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- int major; int minor; int patchlevel;
- The DRM core identifies driver versions by a major, minor and patch
- level triplet. The information is printed to the kernel log at
- initialization time and passed to userspace through the
- DRM_IOCTL_VERSION ioctl.
- The major and minor numbers are also used to verify the requested driver
- API version passed to DRM_IOCTL_SET_VERSION. When the driver API
- changes between minor versions, applications can call
- DRM_IOCTL_SET_VERSION to select a specific version of the API. If the
- requested major isn't equal to the driver major, or the requested minor
- is larger than the driver minor, the DRM_IOCTL_SET_VERSION call will
- return an error. Otherwise the driver's set_version() method will be
- called with the requested version.
- Name, Description and Date
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
- char \*name; char \*desc; char \*date;
- The driver name is printed to the kernel log at initialization time,
- used for IRQ registration and passed to userspace through
- DRM_IOCTL_VERSION.
- The driver description is a purely informative string passed to
- userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by
- the kernel.
- The driver date, formatted as YYYYMMDD, is meant to identify the date of
- the latest modification to the driver. However, as most drivers fail to
- update it, its value is mostly useless. The DRM core prints it to the
- kernel log at initialization time and passes it to userspace through the
- DRM_IOCTL_VERSION ioctl.
- Device Instance and Driver Handling
- -----------------------------------
- .. kernel-doc:: drivers/gpu/drm/drm_drv.c
- :doc: driver instance overview
- .. kernel-doc:: drivers/gpu/drm/drm_drv.c
- :export:
- Driver Load
- -----------
- IRQ Registration
- ~~~~~~~~~~~~~~~~
- The DRM core tries to facilitate IRQ handler registration and
- unregistration by providing :c:func:`drm_irq_install()` and
- :c:func:`drm_irq_uninstall()` functions. Those functions only
- support a single interrupt per device, devices that use more than one
- IRQs need to be handled manually.
- Managed IRQ Registration
- ''''''''''''''''''''''''
- :c:func:`drm_irq_install()` starts by calling the irq_preinstall
- driver operation. The operation is optional and must make sure that the
- interrupt will not get fired by clearing all pending interrupt flags or
- disabling the interrupt.
- The passed-in IRQ will then be requested by a call to
- :c:func:`request_irq()`. If the DRIVER_IRQ_SHARED driver feature
- flag is set, a shared (IRQF_SHARED) IRQ handler will be requested.
- The IRQ handler function must be provided as the mandatory irq_handler
- driver operation. It will get passed directly to
- :c:func:`request_irq()` and thus has the same prototype as all IRQ
- handlers. It will get called with a pointer to the DRM device as the
- second argument.
- Finally the function calls the optional irq_postinstall driver
- operation. The operation usually enables interrupts (excluding the
- vblank interrupt, which is enabled separately), but drivers may choose
- to enable/disable interrupts at a different time.
- :c:func:`drm_irq_uninstall()` is similarly used to uninstall an
- IRQ handler. It starts by waking up all processes waiting on a vblank
- interrupt to make sure they don't hang, and then calls the optional
- irq_uninstall driver operation. The operation must disable all hardware
- interrupts. Finally the function frees the IRQ by calling
- :c:func:`free_irq()`.
- Manual IRQ Registration
- '''''''''''''''''''''''
- Drivers that require multiple interrupt handlers can't use the managed
- IRQ registration functions. In that case IRQs must be registered and
- unregistered manually (usually with the :c:func:`request_irq()` and
- :c:func:`free_irq()` functions, or their :c:func:`devm_request_irq()` and
- :c:func:`devm_free_irq()` equivalents).
- When manually registering IRQs, drivers must not set the
- DRIVER_HAVE_IRQ driver feature flag, and must not provide the
- irq_handler driver operation. They must set the :c:type:`struct
- drm_device <drm_device>` irq_enabled field to 1 upon
- registration of the IRQs, and clear it to 0 after unregistering the
- IRQs.
- Memory Manager Initialization
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Every DRM driver requires a memory manager which must be initialized at
- load time. DRM currently contains two memory managers, the Translation
- Table Manager (TTM) and the Graphics Execution Manager (GEM). This
- document describes the use of the GEM memory manager only. See ? for
- details.
- Miscellaneous Device Configuration
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Another task that may be necessary for PCI devices during configuration
- is mapping the video BIOS. On many devices, the VBIOS describes device
- configuration, LCD panel timings (if any), and contains flags indicating
- device state. Mapping the BIOS can be done using the pci_map_rom()
- call, a convenience function that takes care of mapping the actual ROM,
- whether it has been shadowed into memory (typically at address 0xc0000)
- or exists on the PCI device in the ROM BAR. Note that after the ROM has
- been mapped and any necessary information has been extracted, it should
- be unmapped; on many devices, the ROM address decoder is shared with
- other BARs, so leaving it mapped could cause undesired behaviour like
- hangs or memory corruption.
- Bus-specific Device Registration and PCI Support
- ------------------------------------------------
- A number of functions are provided to help with device registration. The
- functions deal with PCI and platform devices respectively and are only
- provided for historical reasons. These are all deprecated and shouldn't
- be used in new drivers. Besides that there's a few helpers for pci
- drivers.
- .. kernel-doc:: drivers/gpu/drm/drm_pci.c
- :export:
- .. kernel-doc:: drivers/gpu/drm/drm_platform.c
- :export:
- Open/Close, File Operations and IOCTLs
- ======================================
- Open and Close
- --------------
- Open and close handlers. None of those methods are mandatory::
- int (*firstopen) (struct drm_device *);
- void (*lastclose) (struct drm_device *);
- int (*open) (struct drm_device *, struct drm_file *);
- void (*preclose) (struct drm_device *, struct drm_file *);
- void (*postclose) (struct drm_device *, struct drm_file *);
- The firstopen method is called by the DRM core for legacy UMS (User Mode
- Setting) drivers only when an application opens a device that has no
- other opened file handle. UMS drivers can implement it to acquire device
- resources. KMS drivers can't use the method and must acquire resources
- in the load method instead.
- Similarly the lastclose method is called when the last application
- holding a file handle opened on the device closes it, for both UMS and
- KMS drivers. Additionally, the method is also called at module unload
- time or, for hot-pluggable devices, when the device is unplugged. The
- firstopen and lastclose calls can thus be unbalanced.
- The open method is called every time the device is opened by an
- application. Drivers can allocate per-file private data in this method
- and store them in the struct :c:type:`struct drm_file
- <drm_file>` driver_priv field. Note that the open method is
- called before firstopen.
- The close operation is split into preclose and postclose methods.
- Drivers must stop and cleanup all per-file operations in the preclose
- method. For instance pending vertical blanking and page flip events must
- be cancelled. No per-file operation is allowed on the file handle after
- returning from the preclose method.
- Finally the postclose method is called as the last step of the close
- operation, right before calling the lastclose method if no other open
- file handle exists for the device. Drivers that have allocated per-file
- private data in the open method should free it here.
- The lastclose method should restore CRTC and plane properties to default
- value, so that a subsequent open of the device will not inherit state
- from the previous user. It can also be used to execute delayed power
- switching state changes, e.g. in conjunction with the :ref:`vga_switcheroo`
- infrastructure. Beyond that KMS drivers should not do any
- further cleanup. Only legacy UMS drivers might need to clean up device
- state so that the vga console or an independent fbdev driver could take
- over.
- File Operations
- ---------------
- .. kernel-doc:: drivers/gpu/drm/drm_fops.c
- :doc: file operations
- .. kernel-doc:: drivers/gpu/drm/drm_fops.c
- :export:
- IOCTLs
- ------
- struct drm_ioctl_desc \*ioctls; int num_ioctls;
- Driver-specific ioctls descriptors table.
- Driver-specific ioctls numbers start at DRM_COMMAND_BASE. The ioctls
- descriptors table is indexed by the ioctl number offset from the base
- value. Drivers can use the DRM_IOCTL_DEF_DRV() macro to initialize
- the table entries.
- ::
- DRM_IOCTL_DEF_DRV(ioctl, func, flags)
- ``ioctl`` is the ioctl name. Drivers must define the DRM_##ioctl and
- DRM_IOCTL_##ioctl macros to the ioctl number offset from
- DRM_COMMAND_BASE and the ioctl number respectively. The first macro is
- private to the device while the second must be exposed to userspace in a
- public header.
- ``func`` is a pointer to the ioctl handler function compatible with the
- ``drm_ioctl_t`` type.
- ::
- typedef int drm_ioctl_t(struct drm_device *dev, void *data,
- struct drm_file *file_priv);
- ``flags`` is a bitmask combination of the following values. It restricts
- how the ioctl is allowed to be called.
- - DRM_AUTH - Only authenticated callers allowed
- - DRM_MASTER - The ioctl can only be called on the master file handle
- - DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
- - DRM_CONTROL_ALLOW - The ioctl can only be called on a control
- device
- - DRM_UNLOCKED - The ioctl handler will be called without locking the
- DRM global mutex. This is the enforced default for kms drivers (i.e.
- using the DRIVER_MODESET flag) and hence shouldn't be used any more
- for new drivers.
- .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
- :export:
- Legacy Support Code
- ===================
- The section very briefly covers some of the old legacy support code
- which is only used by old DRM drivers which have done a so-called
- shadow-attach to the underlying device instead of registering as a real
- driver. This also includes some of the old generic buffer management and
- command submission code. Do not use any of this in new and modern
- drivers.
- Legacy Suspend/Resume
- ---------------------
- The DRM core provides some suspend/resume code, but drivers wanting full
- suspend/resume support should provide save() and restore() functions.
- These are called at suspend, hibernate, or resume time, and should
- perform any state save or restore required by your device across suspend
- or hibernate states.
- int (\*suspend) (struct drm_device \*, pm_message_t state); int
- (\*resume) (struct drm_device \*);
- Those are legacy suspend and resume methods which *only* work with the
- legacy shadow-attach driver registration functions. New driver should
- use the power management interface provided by their bus type (usually
- through the :c:type:`struct device_driver <device_driver>`
- dev_pm_ops) and set these methods to NULL.
- Legacy DMA Services
- -------------------
- This should cover how DMA mapping etc. is supported by the core. These
- functions are deprecated and should not be used.
|