summaryrefslogtreecommitdiff
path: root/Documentation/DocBook
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-08-01 21:44:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-01 21:44:08 -0400
commit731c7d3a205ba89b475b2aa71b5f13dd6ae3de56 (patch)
treed2b9c3e0a98b94dfc3e4e60e35622c0143ef4ed4 /Documentation/DocBook
parent77a87824ed676ca8ff8482e4157d3adb284fd381 (diff)
parent753e7c8cbd8c503b962294303c7b5e9ea8513443 (diff)
Merge tag 'drm-for-v4.8' of git://people.freedesktop.org/~airlied/linux
Merge drm updates from Dave Airlie: "This is the main drm pull request for 4.8. I'm down with a cold at the moment so hopefully this isn't in too bad a state, I finished pulling stuff last week mostly (nouveau fixes just went in today), so only this message should be influenced by illness. Apologies to anyone who's major feature I missed :-) Core: Lockless GEM BO freeing Non-blocking atomic work Documentation changes (rst/sphinx) Prep for new fencing changes Simple display helpers Master/auth changes Register/unregister rework Loads of trivial patches/fixes. New stuff: ARM Mali display driver (not the 3D chip) sii902x RGB->HDMI bridge Panel: Support for new panels Improved backlight support Bridge: Convert ADV7511 to bridge driver ADV7533 support TC358767 (DSI/DPI to eDP) encoder chip support i915: BXT support enabled by default GVT-g infrastructure GuC command submission and fixes BXT workarounds SKL/BKL workarounds Demidlayering device registration Thundering herd fixes Missing pci ids Atomic updates amdgpu/radeon: ATPX improvements for better dGPU power control on PX systems New power features for CZ/BR/ST Pipelined BO moves and evictions in TTM GPU scheduler improvements GPU reset improvements Overclocking on dGPUs with amdgpu Polaris powermanagement enabled nouveau: GK20A/GM20B volt and clock improvements. Initial support for GP100/GP104 GPUs, GP104 will not yet support acceleration due to NVIDIA having not released firmware for them as of yet. exynos: Exynos5433 SoC with IOMMU support. vc4: Shader validation for branching imx-drm: Atomic mode setting conversion Reworked DMFC FIFO allocation External bridge support analogix-dp: RK3399 eDP support Lots of fixes. rockchip: Lots of small fixes. msm: DT bindings cleanups Shrinker and madvise support ASoC HDMI codec support tegra: Host1x driver cleanups SOR reworking for DP support Runtime PM support omapdrm: PLL enhancements Header refactoring Gamma table support arcgpu: Simulator support virtio-gpu: Atomic modesetting fixes. rcar-du: Misc fixes. mediatek: MT8173 HDMI support sti: ASOC HDMI codec support Minor fixes fsl-dcu: Suspend/resume support Bridge support amdkfd: Minor fixes. etnaviv: Enable GPU clock gating hisilicon: Vblank and other fixes" * tag 'drm-for-v4.8' of git://people.freedesktop.org/~airlied/linux: (1575 commits) drm/nouveau/gr/nv3x: fix instobj write offsets in gr setup drm/nouveau/acpi: fix lockup with PCIe runtime PM drm/nouveau/acpi: check for function 0x1B before using it drm/nouveau/acpi: return supported DSM functions drm/nouveau/acpi: ensure matching ACPI handle and supported functions drm/nouveau/fbcon: fix font width not divisible by 8 drm/amd/powerplay: remove enable_clock_power_gatings_tasks from initialize and resume events drm/amd/powerplay: move clockgating to after ungating power in pp for uvd/vce drm/amdgpu: add query device id and revision id into system info entry at CGS drm/amdgpu: add new definition in bif header drm/amd/powerplay: rename smum header guards drm/amdgpu: enable UVD context buffer for older HW drm/amdgpu: fix default UVD context size drm/amdgpu: fix incorrect type of info_id drm/amdgpu: make amdgpu_cgs_call_acpi_method as static drm/amdgpu: comment out unused defaults_staturn_pro static const structure to fix the build drm/amdgpu: enable UVD VM only on polaris drm/amdgpu: increase timeout of IB test drm/amdgpu: add destroy session when generate VCE destroy msg. drm/amd: fix deadlock of job_list_lock V2 ...
Diffstat (limited to 'Documentation/DocBook')
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/device-drivers.tmpl4
-rw-r--r--Documentation/DocBook/gpu.tmpl3540
3 files changed, 5 insertions, 3541 deletions
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index 01bab5014a4a..8e6dd4b14314 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -16,7 +16,7 @@ DOCBOOKS := z8530book.xml device-drivers.xml \
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
- tracepoint.xml gpu.xml media_api.xml w1.xml \
+ tracepoint.xml media_api.xml w1.xml \
writing_musb_glue_layer.xml crypto-API.xml iio.xml
include Documentation/DocBook/media/Makefile
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
index 99cdc05bbb7a..9c10030eb2be 100644
--- a/Documentation/DocBook/device-drivers.tmpl
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -161,6 +161,10 @@ X!Edrivers/base/interface.c
!Iinclude/linux/fence.h
!Edrivers/dma-buf/seqno-fence.c
!Iinclude/linux/seqno-fence.h
+!Edrivers/dma-buf/fence-array.c
+!Iinclude/linux/fence-array.h
+!Edrivers/dma-buf/reservation.c
+!Iinclude/linux/reservation.h
!Edrivers/dma-buf/sync_file.c
!Iinclude/linux/sync_file.h
</sect2>
diff --git a/Documentation/DocBook/gpu.tmpl b/Documentation/DocBook/gpu.tmpl
deleted file mode 100644
index 7586bf75f62e..000000000000
--- a/Documentation/DocBook/gpu.tmpl
+++ /dev/null
@@ -1,3540 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="gpuDevelopersGuide">
- <bookinfo>
- <title>Linux GPU Driver Developer's Guide</title>
-
- <authorgroup>
- <author>
- <firstname>Jesse</firstname>
- <surname>Barnes</surname>
- <contrib>Initial version</contrib>
- <affiliation>
- <orgname>Intel Corporation</orgname>
- <address>
- <email>jesse.barnes@intel.com</email>
- </address>
- </affiliation>
- </author>
- <author>
- <firstname>Laurent</firstname>
- <surname>Pinchart</surname>
- <contrib>Driver internals</contrib>
- <affiliation>
- <orgname>Ideas on board SPRL</orgname>
- <address>
- <email>laurent.pinchart@ideasonboard.com</email>
- </address>
- </affiliation>
- </author>
- <author>
- <firstname>Daniel</firstname>
- <surname>Vetter</surname>
- <contrib>Contributions all over the place</contrib>
- <affiliation>
- <orgname>Intel Corporation</orgname>
- <address>
- <email>daniel.vetter@ffwll.ch</email>
- </address>
- </affiliation>
- </author>
- <author>
- <firstname>Lukas</firstname>
- <surname>Wunner</surname>
- <contrib>vga_switcheroo documentation</contrib>
- <affiliation>
- <address>
- <email>lukas@wunner.de</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
-
- <copyright>
- <year>2008-2009</year>
- <year>2013-2014</year>
- <holder>Intel Corporation</holder>
- </copyright>
- <copyright>
- <year>2012</year>
- <holder>Laurent Pinchart</holder>
- </copyright>
- <copyright>
- <year>2015</year>
- <holder>Lukas Wunner</holder>
- </copyright>
-
- <legalnotice>
- <para>
- The contents of this file may be used under the terms of the GNU
- General Public License version 2 (the "GPL") as distributed in
- the kernel source COPYING file.
- </para>
- </legalnotice>
-
- <revhistory>
- <!-- Put document revisions here, newest first. -->
- <revision>
- <revnumber>1.0</revnumber>
- <date>2012-07-13</date>
- <authorinitials>LP</authorinitials>
- <revremark>Added extensive documentation about driver internals.
- </revremark>
- </revision>
- <revision>
- <revnumber>1.1</revnumber>
- <date>2015-10-11</date>
- <authorinitials>LW</authorinitials>
- <revremark>Added vga_switcheroo documentation.
- </revremark>
- </revision>
- </revhistory>
- </bookinfo>
-
-<toc></toc>
-
-<part id="drmCore">
- <title>DRM Core</title>
- <partintro>
- <para>
- This first part of the GPU Driver Developer's Guide documents core DRM
- code, helper libraries for writing drivers and generic userspace
- interfaces exposed by DRM drivers.
- </para>
- </partintro>
-
- <chapter id="drmIntroduction">
- <title>Introduction</title>
- <para>
- The Linux DRM layer contains code intended to support the needs
- of complex graphics devices, usually containing programmable
- pipelines well suited to 3D graphics acceleration. Graphics
- drivers in the kernel may make use of DRM functions to make
- tasks like memory management, interrupt handling and DMA easier,
- and provide a uniform interface to applications.
- </para>
- <para>
- A note on versions: this guide covers features found in the DRM
- tree, including the TTM memory manager, output configuration and
- mode setting, and the new vblank internals, in addition to all
- the regular features found in current kernels.
- </para>
- <para>
- [Insert diagram of typical DRM stack here]
- </para>
- <sect1>
- <title>Style Guidelines</title>
- <para>
- For consistency this documentation uses American English. Abbreviations
- are written as all-uppercase, for example: DRM, KMS, IOCTL, CRTC, and so
- on. To aid in reading, documentations make full use of the markup
- characters kerneldoc provides: @parameter for function parameters, @member
- for structure members, &amp;structure to reference structures and
- function() for functions. These all get automatically hyperlinked if
- kerneldoc for the referenced objects exists. When referencing entries in
- function vtables please use -&gt;vfunc(). Note that kerneldoc does
- not support referencing struct members directly, so please add a reference
- to the vtable struct somewhere in the same paragraph or at least section.
- </para>
- <para>
- Except in special situations (to separate locked from unlocked variants)
- locking requirements for functions aren't documented in the kerneldoc.
- Instead locking should be check at runtime using e.g.
- <code>WARN_ON(!mutex_is_locked(...));</code>. Since it's much easier to
- ignore documentation than runtime noise this provides more value. And on
- top of that runtime checks do need to be updated when the locking rules
- change, increasing the chances that they're correct. Within the
- documentation the locking rules should be explained in the relevant
- structures: Either in the comment for the lock explaining what it
- protects, or data fields need a note about which lock protects them, or
- both.
- </para>
- <para>
- Functions which have a non-<code>void</code> return value should have a
- section called "Returns" explaining the expected return values in
- different cases and their meanings. Currently there's no consensus whether
- that section name should be all upper-case or not, and whether it should
- end in a colon or not. Go with the file-local style. Other common section
- names are "Notes" with information for dangerous or tricky corner cases,
- and "FIXME" where the interface could be cleaned up.
- </para>
- </sect1>
- </chapter>
-
- <!-- Internals -->
-
- <chapter id="drmInternals">
- <title>DRM Internals</title>
- <para>
- This chapter documents DRM internals relevant to driver authors
- and developers working to add support for the latest features to
- existing drivers.
- </para>
- <para>
- 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.
- </para>
- <para>
- 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 &amp; fencing, suspend/resume support, and DMA
- services.
- </para>
-
- <!-- Internals: driver init -->
-
- <sect1>
- <title>Driver Initialization</title>
- <para>
- At the core of every DRM driver is a <structname>drm_driver</structname>
- structure. Drivers typically statically initialize a drm_driver structure,
- and then pass it to <function>drm_dev_alloc()</function> to allocate a
- device instance. After the device instance is fully initialized it can be
- registered (which makes it accessible from userspace) using
- <function>drm_dev_register()</function>.
- </para>
- <para>
- The <structname>drm_driver</structname> 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 <structname>drm_driver</structname> static
- information fields, and will then describe individual operations in
- details as they get used in later sections.
- </para>
- <sect2>
- <title>Driver Information</title>
- <sect3>
- <title>Driver Features</title>
- <para>
- Drivers inform the DRM core about their requirements and supported
- features by setting appropriate flags in the
- <structfield>driver_features</structfield> field. Since those flags
- influence the DRM core behaviour since registration time, most of them
- must be set to registering the <structname>drm_driver</structname>
- instance.
- </para>
- <synopsis>u32 driver_features;</synopsis>
- <variablelist>
- <title>Driver Feature Flags</title>
- <varlistentry>
- <term>DRIVER_USE_AGP</term>
- <listitem><para>
- Driver uses AGP interface, the DRM core will manage AGP resources.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_REQUIRE_AGP</term>
- <listitem><para>
- Driver needs AGP interface to function. AGP initialization failure
- will become a fatal error.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_PCI_DMA</term>
- <listitem><para>
- Driver is capable of PCI DMA, mapping of PCI DMA buffers to
- userspace will be enabled. Deprecated.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_SG</term>
- <listitem><para>
- Driver can perform scatter/gather DMA, allocation and mapping of
- scatter/gather buffers will be enabled. Deprecated.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_HAVE_DMA</term>
- <listitem><para>
- Driver supports DMA, the userspace DMA API will be supported.
- Deprecated.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
- <listitem><para>
- 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 <xref linkend="drm-irq-registration"/>.</para>
- <para>DRIVER_IRQ_SHARED indicates whether the device &amp; handler
- support shared IRQs (note that this is required of PCI drivers).
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_GEM</term>
- <listitem><para>
- Driver use the GEM memory manager.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_MODESET</term>
- <listitem><para>
- Driver supports mode setting interfaces (KMS).
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_PRIME</term>
- <listitem><para>
- Driver implements DRM PRIME buffer sharing.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_RENDER</term>
- <listitem><para>
- Driver supports dedicated render nodes.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRIVER_ATOMIC</term>
- <listitem><para>
- 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.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </sect3>
- <sect3>
- <title>Major, Minor and Patchlevel</title>
- <synopsis>int major;
-int minor;
-int patchlevel;</synopsis>
- <para>
- 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.
- </para>
- <para>
- 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.
- </para>
- </sect3>
- <sect3>
- <title>Name, Description and Date</title>
- <synopsis>char *name;
-char *desc;
-char *date;</synopsis>
- <para>
- The driver name is printed to the kernel log at initialization time,
- used for IRQ registration and passed to userspace through
- DRM_IOCTL_VERSION.
- </para>
- <para>
- The driver description is a purely informative string passed to
- userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by
- the kernel.
- </para>
- <para>
- 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.
- </para>
- </sect3>
- </sect2>
- <sect2>
- <title>Device Instance and Driver Handling</title>
-!Pdrivers/gpu/drm/drm_drv.c driver instance overview
-!Edrivers/gpu/drm/drm_drv.c
- </sect2>
- <sect2>
- <title>Driver Load</title>
- <sect3 id="drm-irq-registration">
- <title>IRQ Registration</title>
- <para>
- The DRM core tries to facilitate IRQ handler registration and
- unregistration by providing <function>drm_irq_install</function> and
- <function>drm_irq_uninstall</function> functions. Those functions only
- support a single interrupt per device, devices that use more than one
- IRQs need to be handled manually.
- </para>
- <sect4>
- <title>Managed IRQ Registration</title>
- <para>
- <function>drm_irq_install</function> starts by calling the
- <methodname>irq_preinstall</methodname> 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.
- </para>
- <para>
- The passed-in IRQ will then be requested by a call to
- <function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
- feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
- requested.
- </para>
- <para>
- The IRQ handler function must be provided as the mandatory irq_handler
- driver operation. It will get passed directly to
- <function>request_irq</function> 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.
- </para>
- <para>
- Finally the function calls the optional
- <methodname>irq_postinstall</methodname> 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.
- </para>
- <para>
- <function>drm_irq_uninstall</function> 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
- <methodname>irq_uninstall</methodname> driver operation. The operation
- must disable all hardware interrupts. Finally the function frees the IRQ
- by calling <function>free_irq</function>.
- </para>
- </sect4>
- <sect4>
- <title>Manual IRQ Registration</title>
- <para>
- 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 <function>request_irq</function>
- and <function>free_irq</function> functions, or their devm_* equivalent).
- </para>
- <para>
- When manually registering IRQs, drivers must not set the DRIVER_HAVE_IRQ
- driver feature flag, and must not provide the
- <methodname>irq_handler</methodname> driver operation. They must set the
- <structname>drm_device</structname> <structfield>irq_enabled</structfield>
- field to 1 upon registration of the IRQs, and clear it to 0 after
- unregistering the IRQs.
- </para>
- </sect4>
- </sect3>
- <sect3>
- <title>Memory Manager Initialization</title>
- <para>
- 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
- <xref linkend="drm-memory-management"/> for details.
- </para>
- </sect3>
- <sect3>
- <title>Miscellaneous Device Configuration</title>
- <para>
- 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.
- <!--!Fdrivers/pci/rom.c pci_map_rom-->
- </para>
- </sect3>
- </sect2>
- <sect2>
- <title>Bus-specific Device Registration and PCI Support</title>
- <para>
- 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.
- </para>
-!Edrivers/gpu/drm/drm_pci.c
-!Edrivers/gpu/drm/drm_platform.c
- </sect2>
- </sect1>
-
- <!-- Internals: memory management -->
-
- <sect1 id="drm-memory-management">
- <title>Memory management</title>
- <para>
- Modern Linux systems require large amount of graphics memory to store
- frame buffers, textures, vertices and other graphics-related data. Given
- the very dynamic nature of many of that data, managing graphics memory
- efficiently is thus crucial for the graphics stack and plays a central
- role in the DRM infrastructure.
- </para>
- <para>
- The DRM core includes two memory managers, namely Translation Table Maps
- (TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory
- manager to be developed and tried to be a one-size-fits-them all
- solution. It provides a single userspace API to accommodate the need of
- all hardware, supporting both Unified Memory Architecture (UMA) devices
- and devices with dedicated video RAM (i.e. most discrete video cards).
- This resulted in a large, complex piece of code that turned out to be
- hard to use for driver development.
- </para>
- <para>
- GEM started as an Intel-sponsored project in reaction to TTM's
- complexity. Its design philosophy is completely different: instead of
- providing a solution to every graphics memory-related problems, GEM
- identified common code between drivers and created a support library to
- share it. GEM has simpler initialization and execution requirements than
- TTM, but has no video RAM management capabilities and is thus limited to
- UMA devices.
- </para>
- <sect2>
- <title>The Translation Table Manager (TTM)</title>
- <para>
- TTM design background and information belongs here.
- </para>
- <sect3>
- <title>TTM initialization</title>
- <warning><para>This section is outdated.</para></warning>
- <para>
- Drivers wishing to support TTM must fill out a drm_bo_driver
- structure. The structure contains several fields with function
- pointers for initializing the TTM, allocating and freeing memory,
- waiting for command completion and fence synchronization, and memory
- migration. See the radeon_ttm.c file for an example of usage.
- </para>
- <para>
- The ttm_global_reference structure is made up of several fields:
- </para>
- <programlisting>
- struct ttm_global_reference {
- enum ttm_global_types global_type;
- size_t size;
- void *object;
- int (*init) (struct ttm_global_reference *);
- void (*release) (struct ttm_global_reference *);
- };
- </programlisting>
- <para>
- There should be one global reference structure for your memory
- manager as a whole, and there will be others for each object
- created by the memory manager at runtime. Your global TTM should
- have a type of TTM_GLOBAL_TTM_MEM. The size field for the global
- object should be sizeof(struct ttm_mem_global), and the init and
- release hooks should point at your driver-specific init and
- release routines, which probably eventually call
- ttm_mem_global_init and ttm_mem_global_release, respectively.
- </para>
- <para>
- Once your global TTM accounting structure is set up and initialized
- by calling ttm_global_item_ref() on it,
- you need to create a buffer object TTM to
- provide a pool for buffer object allocation by clients and the
- kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO,
- and its size should be sizeof(struct ttm_bo_global). Again,
- driver-specific init and release functions may be provided,
- likely eventually calling ttm_bo_global_init() and
- ttm_bo_global_release(), respectively. Also, like the previous
- object, ttm_global_item_ref() is used to create an initial reference
- count for the TTM, which will call your initialization function.
- </para>
- </sect3>
- </sect2>
- <sect2 id="drm-gem">
- <title>The Graphics Execution Manager (GEM)</title>
- <para>
- The GEM design approach has resulted in a memory manager that doesn't
- provide full coverage of all (or even all common) use cases in its
- userspace or kernel API. GEM exposes a set of standard memory-related
- operations to userspace and a set of helper functions to drivers, and let
- drivers implement hardware-specific operations with their own private API.
- </para>
- <para>
- The GEM userspace API is described in the
- <ulink url="http://lwn.net/Articles/283798/"><citetitle>GEM - the Graphics
- Execution Manager</citetitle></ulink> article on LWN. While slightly
- outdated, the document provides a good overview of the GEM API principles.
- Buffer allocation and read and write operations, described as part of the
- common GEM API, are currently implemented using driver-specific ioctls.
- </para>
- <para>
- GEM is data-agnostic. It manages abstract buffer objects without knowing
- what individual buffers contain. APIs that require knowledge of buffer
- contents or purpose, such as buffer allocation or synchronization
- primitives, are thus outside of the scope of GEM and must be implemented
- using driver-specific ioctls.
- </para>
- <para>
- On a fundamental level, GEM involves several operations:
- <itemizedlist>
- <listitem>Memory allocation and freeing</listitem>
- <listitem>Command execution</listitem>
- <listitem>Aperture management at command execution time</listitem>
- </itemizedlist>
- Buffer object allocation is relatively straightforward and largely
- provided by Linux's shmem layer, which provides memory to back each
- object.
- </para>
- <para>
- Device-specific operations, such as command execution, pinning, buffer
- read &amp; write, mapping, and domain ownership transfers are left to
- driver-specific ioctls.
- </para>
- <sect3>
- <title>GEM Initialization</title>
- <para>
- Drivers that use GEM must set the DRIVER_GEM bit in the struct
- <structname>drm_driver</structname>
- <structfield>driver_features</structfield> field. The DRM core will
- then automatically initialize the GEM core before calling the
- <methodname>load</methodname> operation. Behind the scene, this will
- create a DRM Memory Manager object which provides an address space
- pool for object allocation.
- </para>
- <para>
- In a KMS configuration, drivers need to allocate and initialize a
- command ring buffer following core GEM initialization if required by
- the hardware. UMA devices usually have what is called a "stolen"
- memory region, which provides space for the initial framebuffer and
- large, contiguous memory regions required by the device. This space is
- typically not managed by GEM, and must be initialized separately into
- its own DRM MM object.
- </para>
- </sect3>
- <sect3>
- <title>GEM Objects Creation</title>
- <para>
- GEM splits creation of GEM objects and allocation of the memory that
- backs them in two distinct operations.
- </para>
- <para>
- GEM objects are represented by an instance of struct
- <structname>drm_gem_object</structname>. Drivers usually need to extend
- GEM objects with private information and thus create a driver-specific
- GEM object structure type that embeds an instance of struct
- <structname>drm_gem_object</structname>.
- </para>
- <para>
- To create a GEM object, a driver allocates memory for an instance of its
- specific GEM object type and initializes the embedded struct
- <structname>drm_gem_object</structname> with a call to
- <function>drm_gem_object_init</function>. The function takes a pointer to
- the DRM device, a pointer to the GEM object and the buffer object size
- in bytes.
- </para>
- <para>
- GEM uses shmem to allocate anonymous pageable memory.
- <function>drm_gem_object_init</function> will create an shmfs file of
- the requested size and store it into the struct
- <structname>drm_gem_object</structname> <structfield>filp</structfield>
- field. The memory is used as either main storage for the object when the
- graphics hardware uses system memory directly or as a backing store
- otherwise.
- </para>
- <para>
- Drivers are responsible for the actual physical pages allocation by
- calling <function>shmem_read_mapping_page_gfp</function> for each page.
- Note that they can decide to allocate pages when initializing the GEM
- object, or to delay allocation until the memory is needed (for instance
- when a page fault occurs as a result of a userspace memory access or
- when the driver needs to start a DMA transfer involving the memory).
- </para>
- <para>
- Anonymous pageable memory allocation is not always desired, for instance
- when the hardware requires physically contiguous system memory as is
- often the case in embedded devices. Drivers can create GEM objects with
- no shmfs backing (called private GEM objects) by initializing them with
- a call to <function>drm_gem_private_object_init</function> instead of
- <function>drm_gem_object_init</function>. Storage for private GEM
- objects must be managed by drivers.
- </para>
- </sect3>
- <sect3>
- <title>GEM Objects Lifetime</title>
- <para>
- All GEM objects are reference-counted by the GEM core. References can be
- acquired and release by <function>calling drm_gem_object_reference</function>
- and <function>drm_gem_object_unreference</function> respectively. The
- caller must hold the <structname>drm_device</structname>
- <structfield>struct_mutex</structfield> lock when calling
- <function>drm_gem_object_reference</function>. As a convenience, GEM
- provides <function>drm_gem_object_unreference_unlocked</function>
- functions that can be called without holding the lock.
- </para>
- <para>
- When the last reference to a GEM object is released the GEM core calls
- the <structname>drm_driver</structname>
- <methodname>gem_free_object</methodname> operation. That operation is
- mandatory for GEM-enabled drivers and must free the GEM object and all
- associated resources.
- </para>
- <para>
- <synopsis>void (*gem_free_object) (struct drm_gem_object *obj);</synopsis>
- Drivers are responsible for freeing all GEM object resources. This includes
- the resources created by the GEM core, which need to be released with
- <function>drm_gem_object_release</function>.
- </para>
- </sect3>
- <sect3>
- <title>GEM Objects Naming</title>
- <para>
- Communication between userspace and the kernel refers to GEM objects
- using local handles, global names or, more recently, file descriptors.
- All of those are 32-bit integer values; the usual Linux kernel limits
- apply to the file descriptors.
- </para>
- <para>
- GEM handles are local to a DRM file. Applications get a handle to a GEM
- object through a driver-specific ioctl, and can use that handle to refer
- to the GEM object in other standard or driver-specific ioctls. Closing a
- DRM file handle frees all its GEM handles and dereferences the
- associated GEM objects.
- </para>
- <para>
- To create a handle for a GEM object drivers call
- <function>drm_gem_handle_create</function>. The function takes a pointer
- to the DRM file and the GEM object and returns a locally unique handle.
- When the handle is no longer needed drivers delete it with a call to
- <function>drm_gem_handle_delete</function>. Finally the GEM object
- associated with a handle can be retrieved by a call to
- <function>drm_gem_object_lookup</function>.
- </para>
- <para>
- Handles don't take ownership of GEM objects, they only take a reference
- to the object that will be dropped when the handle is destroyed. To
- avoid leaking GEM objects, drivers must make sure they drop the
- reference(s) they own (such as the initial reference taken at object
- creation time) as appropriate, without any special consideration for the
- handle. For example, in the particular case of combined GEM object and
- handle creation in the implementation of the
- <methodname>dumb_create</methodname> operation, drivers must drop the
- initial reference to the GEM object before returning the handle.
- </para>
- <para>
- GEM names are similar in purpose to handles but are not local to DRM
- files. They can be passed between processes to reference a GEM object
- globally. Names can't be used directly to refer to objects in the DRM
- API, applications must convert handles to names and names to handles
- using the DRM_IOCTL_GEM_FLINK and DRM_IOCTL_GEM_OPEN ioctls
- respectively. The conversion is handled by the DRM core without any
- driver-specific support.
- </para>
- <para>
- GEM also supports buffer sharing with dma-buf file descriptors through
- PRIME. GEM-based drivers must use the provided helpers functions to
- implement the exporting and importing correctly. See <xref linkend="drm-prime-support" />.
- Since sharing file descriptors is inherently more secure than the
- easily guessable and global GEM names it is the preferred buffer
- sharing mechanism. Sharing buffers through GEM names is only supported
- for legacy userspace. Furthermore PRIME also allows cross-device
- buffer sharing since it is based on dma-bufs.
- </para>
- </sect3>
- <sect3 id="drm-gem-objects-mapping">
- <title>GEM Objects Mapping</title>
- <para>
- Because mapping operations are fairly heavyweight GEM favours
- read/write-like access to buffers, implemented through driver-specific
- ioctls, over mapping buffers to userspace. However, when random access
- to the buffer is needed (to perform software rendering for instance),
- direct access to the object can be more efficient.
- </para>
- <para>
- The mmap system call can't be used directly to map GEM objects, as they
- don't have their own file handle. Two alternative methods currently
- co-exist to map GEM objects to userspace. The first method uses a
- driver-specific ioctl to perform the mapping operation, calling
- <function>do_mmap</function> under the hood. This is often considered
- dubious, seems to be discouraged for new GEM-enabled drivers, and will
- thus not be described here.
- </para>
- <para>
- The second method uses the mmap system call on the DRM file handle.
- <synopsis>void *mmap(void *addr, size_t length, int prot, int flags, int fd,
- off_t offset);</synopsis>
- DRM identifies the GEM object to be mapped by a fake offset passed
- through the mmap offset argument. Prior to being mapped, a GEM object
- must thus be associated with a fake offset. To do so, drivers must call
- <function>drm_gem_create_mmap_offset</function> on the object.
- </para>
- <para>
- Once allocated, the fake offset value
- must be passed to the application in a driver-specific way and can then
- be used as the mmap offset argument.
- </para>
- <para>
- The GEM core provides a helper method <function>drm_gem_mmap</function>
- to handle object mapping. The method can be set directly as the mmap
- file operation handler. It will look up the GEM object based on the
- offset value and set the VMA operations to the
- <structname>drm_driver</structname> <structfield>gem_vm_ops</structfield>
- field. Note that <function>drm_gem_mmap</function> doesn't map memory to
- userspace, but relies on the driver-provided fault handler to map pages
- individually.
- </para>
- <para>
- To use <function>drm_gem_mmap</function>, drivers must fill the struct
- <structname>drm_driver</structname> <structfield>gem_vm_ops</structfield>
- field with a pointer to VM operations.
- </para>
- <para>
- <synopsis>struct vm_operations_struct *gem_vm_ops
-
- struct vm_operations_struct {
- void (*open)(struct vm_area_struct * area);
- void (*close)(struct vm_area_struct * area);
- int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
- };</synopsis>
- </para>
- <para>
- The <methodname>open</methodname> and <methodname>close</methodname>
- operations must update the GEM object reference count. Drivers can use
- the <function>drm_gem_vm_open</function> and
- <function>drm_gem_vm_close</function> helper functions directly as open
- and close handlers.
- </para>
- <para>
- The fault operation handler is responsible for mapping individual pages
- to userspace when a page fault occurs. Depending on the memory
- allocation scheme, drivers can allocate pages at fault time, or can
- decide to allocate memory for the GEM object at the time the object is
- created.
- </para>
- <para>
- Drivers that want to map the GEM object upfront instead of handling page
- faults can implement their own mmap file operation handler.
- </para>
- </sect3>
- <sect3>
- <title>Memory Coherency</title>
- <para>
- When mapped to the device or used in a command buffer, backing pages
- for an object are flushed to memory and marked write combined so as to
- be coherent with the GPU. Likewise, if the CPU accesses an object
- after the GPU has finished rendering to the object, then the object
- must be made coherent with the CPU's view of memory, usually involving
- GPU cache flushing of various kinds. This core CPU&lt;-&gt;GPU
- coherency management is provided by a device-specific ioctl, which
- evaluates an object's current domain and performs any necessary
- flushing or synchronization to put the object into the desired
- coherency domain (note that the object may be busy, i.e. an active
- render target; in that case, setting the domain blocks the client and
- waits for rendering to complete before performing any necessary
- flushing operations).
- </para>
- </sect3>
- <sect3>
- <title>Command Execution</title>
- <para>
- Perhaps the most important GEM function for GPU devices is providing a
- command execution interface to clients. Client programs construct
- command buffers containing references to previously allocated memory
- objects, and then submit them to GEM. At that point, GEM takes care to
- bind all the objects into the GTT, execute the buffer, and provide
- necessary synchronization between clients accessing the same buffers.
- This often involves evicting some objects from the GTT and re-binding
- others (a fairly expensive operation), and providing relocation
- support which hides fixed GTT offsets from clients. Clients must take
- care not to submit command buffers that reference more objects than
- can fit in the GTT; otherwise, GEM will reject them and no rendering
- will occur. Similarly, if several objects in the buffer require fence
- registers to be allocated for correct rendering (e.g. 2D blits on
- pre-965 chips), care must be taken not to require more fence registers
- than are available to the client. Such resource management should be
- abstracted from the client in libdrm.
- </para>
- </sect3>
- </sect2>
- <sect2>
- <title>GEM Function Reference</title>
-!Edrivers/gpu/drm/drm_gem.c
-!Iinclude/drm/drm_gem.h
- </sect2>
- <sect2>
- <title>VMA Offset Manager</title>
-!Pdrivers/gpu/drm/drm_vma_manager.c vma offset manager
-!Edrivers/gpu/drm/drm_vma_manager.c
-!Iinclude/drm/drm_vma_manager.h
- </sect2>
- <sect2 id="drm-prime-support">
- <title>PRIME Buffer Sharing</title>
- <para>
- PRIME is the cross device buffer sharing framework in drm, originally
- created for the OPTIMUS range of multi-gpu platforms. To userspace
- PRIME buffers are dma-buf based file descriptors.
- </para>
- <sect3>
- <title>Overview and Driver Interface</title>
- <para>
- Similar to GEM global names, PRIME file descriptors are
- also used to share buffer objects across processes. They offer
- additional security: as file descriptors must be explicitly sent over
- UNIX domain sockets to be shared between applications, they can't be
- guessed like the globally unique GEM names.
- </para>
- <para>
- Drivers that support the PRIME
- API must set the DRIVER_PRIME bit in the struct
- <structname>drm_driver</structname>
- <structfield>driver_features</structfield> field, and implement the
- <methodname>prime_handle_to_fd</methodname> and
- <methodname>prime_fd_to_handle</methodname> operations.
- </para>
- <para>
- <synopsis>int (*prime_handle_to_fd)(struct drm_device *dev,
- struct drm_file *file_priv, uint32_t handle,
- uint32_t flags, int *prime_fd);
-int (*prime_fd_to_handle)(struct drm_device *dev,
- struct drm_file *file_priv, int prime_fd,
- uint32_t *handle);</synopsis>
- Those two operations convert a handle to a PRIME file descriptor and
- vice versa. Drivers must use the kernel dma-buf buffer sharing framework
- to manage the PRIME file descriptors. Similar to the mode setting
- API PRIME is agnostic to the underlying buffer object manager, as
- long as handles are 32bit unsigned integers.
- </para>
- <para>
- While non-GEM drivers must implement the operations themselves, GEM
- drivers must use the <function>drm_gem_prime_handle_to_fd</function>
- and <function>drm_gem_prime_fd_to_handle</function> helper functions.
- Those helpers rely on the driver
- <methodname>gem_prime_export</methodname> and
- <methodname>gem_prime_import</methodname> operations to create a dma-buf
- instance from a GEM object (dma-buf exporter role) and to create a GEM
- object from a dma-buf instance (dma-buf importer role).
- </para>
- <para>
- <synopsis>struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
- struct drm_gem_object *obj,
- int flags);
-struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
- struct dma_buf *dma_buf);</synopsis>
- These two operations are mandatory for GEM drivers that support
- PRIME.
- </para>
- </sect3>
- <sect3>
- <title>PRIME Helper Functions</title>
-!Pdrivers/gpu/drm/drm_prime.c PRIME Helpers
- </sect3>
- </sect2>
- <sect2>
- <title>PRIME Function References</title>
-!Edrivers/gpu/drm/drm_prime.c
- </sect2>
- <sect2>
- <title>DRM MM Range Allocator</title>
- <sect3>
- <title>Overview</title>
-!Pdrivers/gpu/drm/drm_mm.c Overview
- </sect3>
- <sect3>
- <title>LRU Scan/Eviction Support</title>
-!Pdrivers/gpu/drm/drm_mm.c lru scan roaster
- </sect3>
- </sect2>
- <sect2>
- <title>DRM MM Range Allocator Function References</title>
-!Edrivers/gpu/drm/drm_mm.c
-!Iinclude/drm/drm_mm.h
- </sect2>
- <sect2>
- <title>CMA Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_gem_cma_helper.c cma helpers
-!Edrivers/gpu/drm/drm_gem_cma_helper.c
-!Iinclude/drm/drm_gem_cma_helper.h
- </sect2>
- </sect1>
-
- <!-- Internals: mode setting -->
-
- <sect1 id="drm-mode-setting">
- <title>Mode Setting</title>
- <para>
- Drivers must initialize the mode setting core by calling
- <function>drm_mode_config_init</function> on the DRM device. The function
- initializes the <structname>drm_device</structname>
- <structfield>mode_config</structfield> field and never fails. Once done,
- mode configuration must be setup by initializing the following fields.
- </para>
- <itemizedlist>
- <listitem>
- <synopsis>int min_width, min_height;
-int max_width, max_height;</synopsis>
- <para>
- Minimum and maximum width and height of the frame buffers in pixel
- units.
- </para>
- </listitem>
- <listitem>
- <synopsis>struct drm_mode_config_funcs *funcs;</synopsis>
- <para>Mode setting functions.</para>
- </listitem>
- </itemizedlist>
- <sect2>
- <title>Display Modes Function Reference</title>
-!Iinclude/drm/drm_modes.h
-!Edrivers/gpu/drm/drm_modes.c
- </sect2>
- <sect2>
- <title>Atomic Mode Setting Function Reference</title>
-!Edrivers/gpu/drm/drm_atomic.c
-!Idrivers/gpu/drm/drm_atomic.c
- </sect2>
- <sect2>
- <title>Frame Buffer Abstraction</title>
- <para>
- Frame buffers are abstract memory objects that provide a source of
- pixels to scanout to a CRTC. Applications explicitly request the
- creation of frame buffers through the DRM_IOCTL_MODE_ADDFB(2) ioctls and
- receive an opaque handle that can be passed to the KMS CRTC control,
- plane configuration and page flip functions.
- </para>
- <para>
- Frame buffers rely on the underneath memory manager for low-level memory
- operations. When creating a frame buffer applications pass a memory
- handle (or a list of memory handles for multi-planar formats) through
- the <parameter>drm_mode_fb_cmd2</parameter> argument. For drivers using
- GEM as their userspace buffer management interface this would be a GEM
- handle. Drivers are however free to use their own backing storage object
- handles, e.g. vmwgfx directly exposes special TTM handles to userspace
- and so expects TTM handles in the create ioctl and not GEM handles.
- </para>
- <para>
- The lifetime of a drm framebuffer is controlled with a reference count,
- drivers can grab additional references with
- <function>drm_framebuffer_reference</function>and drop them
- again with <function>drm_framebuffer_unreference</function>. For
- driver-private framebuffers for which the last reference is never
- dropped (e.g. for the fbdev framebuffer when the struct
- <structname>drm_framebuffer</structname> is embedded into the fbdev
- helper struct) drivers can manually clean up a framebuffer at module
- unload time with
- <function>drm_framebuffer_unregister_private</function>.
- </para>
- </sect2>
- <sect2>
- <title>Dumb Buffer Objects</title>
- <para>
- The KMS API doesn't standardize backing storage object creation and
- leaves it to driver-specific ioctls. Furthermore actually creating a
- buffer object even for GEM-based drivers is done through a
- driver-specific ioctl - GEM only has a common userspace interface for
- sharing and destroying objects. While not an issue for full-fledged
- graphics stacks that include device-specific userspace components (in
- libdrm for instance), this limit makes DRM-based early boot graphics
- unnecessarily complex.
- </para>
- <para>
- Dumb objects partly alleviate the problem by providing a standard
- API to create dumb buffers suitable for scanout, which can then be used
- to create KMS frame buffers.
- </para>
- <para>
- To support dumb objects drivers must implement the
- <methodname>dumb_create</methodname>,
- <methodname>dumb_destroy</methodname> and
- <methodname>dumb_map_offset</methodname> operations.
- </para>
- <itemizedlist>
- <listitem>
- <synopsis>int (*dumb_create)(struct drm_file *file_priv, struct drm_device *dev,
- struct drm_mode_create_dumb *args);</synopsis>
- <para>
- The <methodname>dumb_create</methodname> operation creates a driver
- object (GEM or TTM handle) suitable for scanout based on the
- width, height and depth from the struct
- <structname>drm_mode_create_dumb</structname> argument. It fills the
- argument's <structfield>handle</structfield>,
- <structfield>pitch</structfield> and <structfield>size</structfield>
- fields with a handle for the newly created object and its line
- pitch and size in bytes.
- </para>
- </listitem>
- <listitem>
- <synopsis>int (*dumb_destroy)(struct drm_file *file_priv, struct drm_device *dev,
- uint32_t handle);</synopsis>
- <para>
- The <methodname>dumb_destroy</methodname> operation destroys a dumb
- object created by <methodname>dumb_create</methodname>.
- </para>
- </listitem>
- <listitem>
- <synopsis>int (*dumb_map_offset)(struct drm_file *file_priv, struct drm_device *dev,
- uint32_t handle, uint64_t *offset);</synopsis>
- <para>
- The <methodname>dumb_map_offset</methodname> operation associates an
- mmap fake offset with the object given by the handle and returns
- it. Drivers must use the
- <function>drm_gem_create_mmap_offset</function> function to
- associate the fake offset as described in
- <xref linkend="drm-gem-objects-mapping"/>.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Note that dumb objects may not be used for gpu acceleration, as has been
- attempted on some ARM embedded platforms. Such drivers really must have
- a hardware-specific ioctl to allocate suitable buffer objects.
- </para>
- </sect2>
- <sect2>
- <title>Output Polling</title>
- <synopsis>void (*output_poll_changed)(struct drm_device *dev);</synopsis>
- <para>
- This operation notifies the driver that the status of one or more
- connectors has changed. Drivers that use the fb helper can just call the
- <function>drm_fb_helper_hotplug_event</function> function to handle this
- operation.
- </para>
- </sect2>
- <sect2>
- <title>Locking</title>
- <para>
- Beside some lookup structures with their own locking (which is hidden
- behind the interface functions) most of the modeset state is protected
- by the <code>dev-&lt;mode_config.lock</code> mutex and additionally
- per-crtc locks to allow cursor updates, pageflips and similar operations
- to occur concurrently with background tasks like output detection.
- Operations which cross domains like a full modeset always grab all
- locks. Drivers there need to protect resources shared between crtcs with
- additional locking. They also need to be careful to always grab the
- relevant crtc locks if a modset functions touches crtc state, e.g. for
- load detection (which does only grab the <code>mode_config.lock</code>
- to allow concurrent screen updates on live crtcs).
- </para>
- </sect2>
- </sect1>
-
- <!-- Internals: kms initialization and cleanup -->
-
- <sect1 id="drm-kms-init">
- <title>KMS Initialization and Cleanup</title>
- <para>
- A KMS device is abstracted and exposed as a set of planes, CRTCs, encoders
- and connectors. KMS drivers must thus create and initialize all those
- objects at load time after initializing mode setting.
- </para>
- <sect2>
- <title>CRTCs (struct <structname>drm_crtc</structname>)</title>
- <para>
- A CRTC is an abstraction representing a part of the chip that contains a
- pointer to a scanout buffer. Therefore, the number of CRTCs available
- determines how many independent scanout buffers can be active at any
- given time. The CRTC structure contains several fields to support this:
- a pointer to some video memory (abstracted as a frame buffer object), a
- display mode, and an (x, y) offset into the video memory to support
- panning or configurations where one piece of video memory spans multiple
- CRTCs.
- </para>
- <sect3>
- <title>CRTC Initialization</title>
- <para>
- A KMS device must create and register at least one struct
- <structname>drm_crtc</structname> instance. The instance is allocated
- and zeroed by the driver, possibly as part of a larger structure, and
- registered with a call to <function>drm_crtc_init</function> with a
- pointer to CRTC functions.
- </para>
- </sect3>
- </sect2>
- <sect2>
- <title>Planes (struct <structname>drm_plane</structname>)</title>
- <para>
- A plane represents an image source that can be blended with or overlayed
- on top of a CRTC during the scanout process. Planes are associated with
- a frame buffer to crop a portion of the image memory (source) and
- optionally scale it to a destination size. The result is then blended
- with or overlayed on top of a CRTC.
- </para>
- <para>
- The DRM core recognizes three types of planes:
- <itemizedlist>
- <listitem>
- DRM_PLANE_TYPE_PRIMARY represents a "main" plane for a CRTC. Primary
- planes are the planes operated upon by CRTC modesetting and flipping
- operations described in the page_flip hook in <structname>drm_crtc_funcs</structname>.
- </listitem>
- <listitem>
- DRM_PLANE_TYPE_CURSOR represents a "cursor" plane for a CRTC. Cursor
- planes are the planes operated upon by the DRM_IOCTL_MODE_CURSOR and
- DRM_IOCTL_MODE_CURSOR2 ioctls.
- </listitem>
- <listitem>
- DRM_PLANE_TYPE_OVERLAY represents all non-primary, non-cursor planes.
- Some drivers refer to these types of planes as "sprites" internally.
- </listitem>
- </itemizedlist>
- For compatibility with legacy userspace, only overlay planes are made
- available to userspace by default. Userspace clients may set the
- DRM_CLIENT_CAP_UNIVERSAL_PLANES client capability bit to indicate that
- they wish to receive a universal plane list containing all plane types.
- </para>
- <sect3>
- <title>Plane Initialization</title>
- <para>
- To create a plane, a KMS drivers allocates and
- zeroes an instances of struct <structname>drm_plane</structname>
- (possibly as part of a larger structure) and registers it with a call
- to <function>drm_universal_plane_init</function>. The function takes a bitmask
- of the CRTCs that can be associated with the plane, a pointer to the
- plane functions, a list of format supported formats, and the type of
- plane (primary, cursor, or overlay) being initialized.
- </para>
- <para>
- Cursor and overlay planes are optional. All drivers should provide
- one primary plane per CRTC (although this requirement may change in
- the future); drivers that do not wish to provide special handling for
- primary planes may make use of the helper functions described in
- <xref linkend="drm-kms-planehelpers"/> to create and register a
- primary plane with standard capabilities.
- </para>
- </sect3>
- </sect2>
- <sect2>
- <title>Encoders (struct <structname>drm_encoder</structname>)</title>
- <para>
- An encoder takes pixel data from a CRTC and converts it to a format
- suitable for any attached connectors. On some devices, it may be
- possible to have a CRTC send data to more than one encoder. In that
- case, both encoders would receive data from the same scanout buffer,
- resulting in a "cloned" display configuration across the connectors
- attached to each encoder.
- </para>
- <sect3>
- <title>Encoder Initialization</title>
- <para>
- As for CRTCs, a KMS driver must create, initialize and register at
- least one struct <structname>drm_encoder</structname> instance. The
- instance is allocated and zeroed by the driver, possibly as part of a
- larger structure.
- </para>
- <para>
- Drivers must initialize the struct <structname>drm_encoder</structname>
- <structfield>possible_crtcs</structfield> and
- <structfield>possible_clones</structfield> fields before registering the
- encoder. Both fields are bitmasks of respectively the CRTCs that the
- encoder can be connected to, and sibling encoders candidate for cloning.
- </para>
- <para>
- After being initialized, the encoder must be registered with a call to
- <function>drm_encoder_init</function>. The function takes a pointer to
- the encoder functions and an encoder type. Supported types are
- <itemizedlist>
- <listitem>
- DRM_MODE_ENCODER_DAC for VGA and analog on DVI-I/DVI-A
- </listitem>
- <listitem>
- DRM_MODE_ENCODER_TMDS for DVI, HDMI and (embedded) DisplayPort
- </listitem>
- <listitem>
- DRM_MODE_ENCODER_LVDS for display panels
- </listitem>
- <listitem>
- DRM_MODE_ENCODER_TVDAC for TV output (Composite, S-Video, Component,
- SCART)
- </listitem>
- <listitem>
- DRM_MODE_ENCODER_VIRTUAL for virtual machine displays
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Encoders must be attached to a CRTC to be used. DRM drivers leave
- encoders unattached at initialization time. Applications (or the fbdev
- compatibility layer when implemented) are responsible for attaching the
- encoders they want to use to a CRTC.
- </para>
- </sect3>
- </sect2>
- <sect2>
- <title>Connectors (struct <structname>drm_connector</structname>)</title>
- <para>
- A connector is the final destination for pixel data on a device, and
- usually connects directly to an external display device like a monitor
- or laptop panel. A connector can only be attached to one encoder at a
- time. The connector is also the structure where information about the
- attached display is kept, so it contains fields for display data, EDID
- data, DPMS &amp; connection status, and information about modes
- supported on the attached displays.
- </para>
- <sect3>
- <title>Connector Initialization</title>
- <para>
- Finally a KMS driver must create, initialize, register and attach at
- least one struct <structname>drm_connector</structname> instance. The
- instance is created as other KMS objects and initialized by setting the
- following fields.
- </para>
- <variablelist>
- <varlistentry>
- <term><structfield>interlace_allowed</structfield></term>
- <listitem><para>
- Whether the connector can handle interlaced modes.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><structfield>doublescan_allowed</structfield></term>
- <listitem><para>
- Whether the connector can handle doublescan.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><structfield>display_info
- </structfield></term>
- <listitem><para>
- Display information is filled from EDID information when a display
- is detected. For non hot-pluggable displays such as flat panels in
- embedded systems, the driver should initialize the
- <structfield>display_info</structfield>.<structfield>width_mm</structfield>
- and
- <structfield>display_info</structfield>.<structfield>height_mm</structfield>
- fields with the physical size of the display.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term id="drm-kms-connector-polled"><structfield>polled</structfield></term>
- <listitem><para>
- Connector polling mode, a combination of
- <variablelist>
- <varlistentry>
- <term>DRM_CONNECTOR_POLL_HPD</term>
- <listitem><para>
- The connector generates hotplug events and doesn't need to be
- periodically polled. The CONNECT and DISCONNECT flags must not
- be set together with the HPD flag.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRM_CONNECTOR_POLL_CONNECT</term>
- <listitem><para>
- Periodically poll the connector for connection.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRM_CONNECTOR_POLL_DISCONNECT</term>
- <listitem><para>
- Periodically poll the connector for disconnection.
- </para></listitem>
- </varlistentry>
- </variablelist>
- Set to 0 for connectors that don't support connection status
- discovery.
- </para></listitem>
- </varlistentry>
- </variablelist>
- <para>
- The connector is then registered with a call to
- <function>drm_connector_init</function> with a pointer to the connector
- functions and a connector type, and exposed through sysfs with a call to
- <function>drm_connector_register</function>.
- </para>
- <para>
- Supported connector types are
- <itemizedlist>
- <listitem>DRM_MODE_CONNECTOR_VGA</listitem>
- <listitem>DRM_MODE_CONNECTOR_DVII</listitem>
- <listitem>DRM_MODE_CONNECTOR_DVID</listitem>
- <listitem>DRM_MODE_CONNECTOR_DVIA</listitem>
- <listitem>DRM_MODE_CONNECTOR_Composite</listitem>
- <listitem>DRM_MODE_CONNECTOR_SVIDEO</listitem>
- <listitem>DRM_MODE_CONNECTOR_LVDS</listitem>
- <listitem>DRM_MODE_CONNECTOR_Component</listitem>
- <listitem>DRM_MODE_CONNECTOR_9PinDIN</listitem>
- <listitem>DRM_MODE_CONNECTOR_DisplayPort</listitem>
- <listitem>DRM_MODE_CONNECTOR_HDMIA</listitem>
- <listitem>DRM_MODE_CONNECTOR_HDMIB</listitem>
- <listitem>DRM_MODE_CONNECTOR_TV</listitem>
- <listitem>DRM_MODE_CONNECTOR_eDP</listitem>
- <listitem>DRM_MODE_CONNECTOR_VIRTUAL</listitem>
- </itemizedlist>
- </para>
- <para>
- Connectors must be attached to an encoder to be used. For devices that
- map connectors to encoders 1:1, the connector should be attached at
- initialization time with a call to
- <function>drm_mode_connector_attach_encoder</function>. The driver must
- also set the <structname>drm_connector</structname>
- <structfield>encoder</structfield> field to point to the attached
- encoder.
- </para>
- <para>
- Finally, drivers must initialize the connectors state change detection
- with a call to <function>drm_kms_helper_poll_init</function>. If at
- least one connector is pollable but can't generate hotplug interrupts
- (indicated by the DRM_CONNECTOR_POLL_CONNECT and
- DRM_CONNECTOR_POLL_DISCONNECT connector flags), a delayed work will
- automatically be queued to periodically poll for changes. Connectors
- that can generate hotplug interrupts must be marked with the
- DRM_CONNECTOR_POLL_HPD flag instead, and their interrupt handler must
- call <function>drm_helper_hpd_irq_event</function>. The function will
- queue a delayed work to check the state of all connectors, but no
- periodic polling will be done.
- </para>
- </sect3>
- <sect3>
- <title>Connector Operations</title>
- <note><para>
- Unless otherwise state, all operations are mandatory.
- </para></note>
- <sect4>
- <title>DPMS</title>
- <synopsis>void (*dpms)(struct drm_connector *connector, int mode);</synopsis>
- <para>
- The DPMS operation sets the power state of a connector. The mode
- argument is one of
- <itemizedlist>
- <listitem><para>DRM_MODE_DPMS_ON</para></listitem>
- <listitem><para>DRM_MODE_DPMS_STANDBY</para></listitem>
- <listitem><para>DRM_MODE_DPMS_SUSPEND</para></listitem>
- <listitem><para>DRM_MODE_DPMS_OFF</para></listitem>
- </itemizedlist>
- </para>
- <para>
- In all but DPMS_ON mode the encoder to which the connector is attached
- should put the display in low-power mode by driving its signals
- appropriately. If more than one connector is attached to the encoder
- care should be taken not to change the power state of other displays as
- a side effect. Low-power mode should be propagated to the encoders and
- CRTCs when all related connectors are put in low-power mode.
- </para>
- </sect4>
- <sect4>
- <title>Modes</title>
- <synopsis>int (*fill_modes)(struct drm_connector *connector, uint32_t max_width,
- uint32_t max_height);</synopsis>
- <para>
- Fill the mode list with all supported modes for the connector. If the
- <parameter>max_width</parameter> and <parameter>max_height</parameter>
- arguments are non-zero, the implementation must ignore all modes wider
- than <parameter>max_width</parameter> or higher than
- <parameter>max_height</parameter>.
- </para>
- <para>
- The connector must also fill in this operation its
- <structfield>display_info</structfield>
- <structfield>width_mm</structfield> and
- <structfield>height_mm</structfield> fields with the connected display
- physical size in millimeters. The fields should be set to 0 if the value
- isn't known or is not applicable (for instance for projector devices).
- </para>
- </sect4>
- <sect4>
- <title>Connection Status</title>
- <para>
- The connection status is updated through polling or hotplug events when
- supported (see <xref linkend="drm-kms-connector-polled"/>). The status
- value is reported to userspace through ioctls and must not be used
- inside the driver, as it only gets initialized by a call to
- <function>drm_mode_getconnector</function> from userspace.
- </para>
- <synopsis>enum drm_connector_status (*detect)(struct drm_connector *connector,
- bool force);</synopsis>
- <para>
- Check to see if anything is attached to the connector. The
- <parameter>force</parameter> parameter is set to false whilst polling or
- to true when checking the connector due to user request.
- <parameter>force</parameter> can be used by the driver to avoid
- expensive, destructive operations during automated probing.
- </para>
- <para>
- Return connector_status_connected if something is connected to the
- connector, connector_status_disconnected if nothing is connected and
- connector_status_unknown if the connection state isn't known.
- </para>
- <para>
- Drivers should only return connector_status_connected if the connection
- status has really been probed as connected. Connectors that can't detect
- the connection status, or failed connection status probes, should return
- connector_status_unknown.
- </para>
- </sect4>
- </sect3>
- </sect2>
- <sect2>
- <title>Cleanup</title>
- <para>
- The DRM core manages its objects' lifetime. When an object is not needed
- anymore the core calls its destroy function, which must clean up and
- free every resource allocated for the object. Every
- <function>drm_*_init</function> call must be matched with a
- corresponding <function>drm_*_cleanup</function> call to cleanup CRTCs
- (<function>drm_crtc_cleanup</function>), planes
- (<function>drm_plane_cleanup</function>), encoders
- (<function>drm_encoder_cleanup</function>) and connectors
- (<function>drm_connector_cleanup</function>). Furthermore, connectors
- that have been added to sysfs must be removed by a call to
- <function>drm_connector_unregister</function> before calling
- <function>drm_connector_cleanup</function>.
- </para>
- <para>
- Connectors state change detection must be cleanup up with a call to
- <function>drm_kms_helper_poll_fini</function>.
- </para>
- </sect2>
- <sect2>
- <title>Output discovery and initialization example</title>
- <programlisting><![CDATA[
-void intel_crt_init(struct drm_device *dev)
-{
- struct drm_connector *connector;
- struct intel_output *intel_output;
-
- intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
- if (!intel_output)
- return;
-
- connector = &intel_output->base;
- drm_connector_init(dev, &intel_output->base,
- &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
-
- drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs,
- DRM_MODE_ENCODER_DAC);
-
- drm_mode_connector_attach_encoder(&intel_output->base,
- &intel_output->enc);
-
- /* Set up the DDC bus. */
- intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
- if (!intel_output->ddc_bus) {
- dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
- "failed.\n");
- return;
- }
-
- intel_output->type = INTEL_OUTPUT_ANALOG;
- connector->interlace_allowed = 0;
- connector->doublescan_allowed = 0;
-
- drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
- drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
-
- drm_connector_register(connector);
-}]]></programlisting>
- <para>
- In the example above (taken from the i915 driver), a CRTC, connector and
- encoder combination is created. A device-specific i2c bus is also
- created for fetching EDID data and performing monitor detection. Once
- the process is complete, the new connector is registered with sysfs to
- make its properties available to applications.
- </para>
- </sect2>
- <sect2>
- <title>KMS API Functions</title>
-!Edrivers/gpu/drm/drm_crtc.c
- </sect2>
- <sect2>
- <title>KMS Data Structures</title>
-!Iinclude/drm/drm_crtc.h
- </sect2>
- <sect2>
- <title>KMS Locking</title>
-!Pdrivers/gpu/drm/drm_modeset_lock.c kms locking
-!Iinclude/drm/drm_modeset_lock.h
-!Edrivers/gpu/drm/drm_modeset_lock.c
- </sect2>
- </sect1>
-
- <!-- Internals: kms helper functions -->
-
- <sect1>
- <title>Mode Setting Helper Functions</title>
- <para>
- The plane, CRTC, encoder and connector functions provided by the drivers
- implement the DRM API. They're called by the DRM core and ioctl handlers
- to handle device state changes and configuration request. As implementing
- those functions often requires logic not specific to drivers, mid-layer
- helper functions are available to avoid duplicating boilerplate code.
- </para>
- <para>
- The DRM core contains one mid-layer implementation. The mid-layer provides
- implementations of several plane, CRTC, encoder and connector functions
- (called from the top of the mid-layer) that pre-process requests and call
- lower-level functions provided by the driver (at the bottom of the
- mid-layer). For instance, the
- <function>drm_crtc_helper_set_config</function> function can be used to
- fill the struct <structname>drm_crtc_funcs</structname>
- <structfield>set_config</structfield> field. When called, it will split
- the <methodname>set_config</methodname> operation in smaller, simpler
- operations and call the driver to handle them.
- </para>
- <para>
- To use the mid-layer, drivers call <function>drm_crtc_helper_add</function>,
- <function>drm_encoder_helper_add</function> and
- <function>drm_connector_helper_add</function> functions to install their
- mid-layer bottom operations handlers, and fill the
- <structname>drm_crtc_funcs</structname>,
- <structname>drm_encoder_funcs</structname> and
- <structname>drm_connector_funcs</structname> structures with pointers to
- the mid-layer top API functions. Installing the mid-layer bottom operation
- handlers is best done right after registering the corresponding KMS object.
- </para>
- <para>
- The mid-layer is not split between CRTC, encoder and connector operations.
- To use it, a driver must provide bottom functions for all of the three KMS
- entities.
- </para>
- <sect2>
- <title>Atomic Modeset Helper Functions Reference</title>
- <sect3>
- <title>Overview</title>
-!Pdrivers/gpu/drm/drm_atomic_helper.c overview
- </sect3>
- <sect3>
- <title>Implementing Asynchronous Atomic Commit</title>
-!Pdrivers/gpu/drm/drm_atomic_helper.c implementing async commit
- </sect3>
- <sect3>
- <title>Atomic State Reset and Initialization</title>
-!Pdrivers/gpu/drm/drm_atomic_helper.c atomic state reset and initialization
- </sect3>
-!Iinclude/drm/drm_atomic_helper.h
-!Edrivers/gpu/drm/drm_atomic_helper.c
- </sect2>
- <sect2>
- <title>Modeset Helper Reference for Common Vtables</title>
-!Iinclude/drm/drm_modeset_helper_vtables.h
-!Pinclude/drm/drm_modeset_helper_vtables.h overview
- </sect2>
- <sect2>
- <title>Legacy CRTC/Modeset Helper Functions Reference</title>
-!Edrivers/gpu/drm/drm_crtc_helper.c
-!Pdrivers/gpu/drm/drm_crtc_helper.c overview
- </sect2>
- <sect2>
- <title>Output Probing Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_probe_helper.c output probing helper overview
-!Edrivers/gpu/drm/drm_probe_helper.c
- </sect2>
- <sect2>
- <title>fbdev Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers
-!Edrivers/gpu/drm/drm_fb_helper.c
-!Iinclude/drm/drm_fb_helper.h
- </sect2>
- <sect2>
- <title>Framebuffer CMA Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_fb_cma_helper.c framebuffer cma helper functions
-!Edrivers/gpu/drm/drm_fb_cma_helper.c
- </sect2>
- <sect2>
- <title>Display Port Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_dp_helper.c dp helpers
-!Iinclude/drm/drm_dp_helper.h
-!Edrivers/gpu/drm/drm_dp_helper.c
- </sect2>
- <sect2>
- <title>Display Port Dual Mode Adaptor Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_dp_dual_mode_helper.c dp dual mode helpers
-!Iinclude/drm/drm_dp_dual_mode_helper.h
-!Edrivers/gpu/drm/drm_dp_dual_mode_helper.c
- </sect2>
- <sect2>
- <title>Display Port MST Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_dp_mst_topology.c dp mst helper
-!Iinclude/drm/drm_dp_mst_helper.h
-!Edrivers/gpu/drm/drm_dp_mst_topology.c
- </sect2>
- <sect2>
- <title>MIPI DSI Helper Functions Reference</title>
-!Pdrivers/gpu/drm/drm_mipi_dsi.c dsi helpers
-!Iinclude/drm/drm_mipi_dsi.h
-!Edrivers/gpu/drm/drm_mipi_dsi.c
- </sect2>
- <sect2>
- <title>EDID Helper Functions Reference</title>
-!Edrivers/gpu/drm/drm_edid.c
- </sect2>
- <sect2>
- <title>Rectangle Utilities Reference</title>
-!Pinclude/drm/drm_rect.h rect utils
-!Iinclude/drm/drm_rect.h
-!Edrivers/gpu/drm/drm_rect.c
- </sect2>
- <sect2>
- <title>Flip-work Helper Reference</title>
-!Pinclude/drm/drm_flip_work.h flip utils
-!Iinclude/drm/drm_flip_work.h
-!Edrivers/gpu/drm/drm_flip_work.c
- </sect2>
- <sect2>
- <title>HDMI Infoframes Helper Reference</title>
- <para>
- Strictly speaking this is not a DRM helper library but generally useable
- by any driver interfacing with HDMI outputs like v4l or alsa drivers.
- But it nicely fits into the overall topic of mode setting helper
- libraries and hence is also included here.
- </para>
-!Iinclude/linux/hdmi.h
-!Edrivers/video/hdmi.c
- </sect2>
- <sect2>
- <title id="drm-kms-planehelpers">Plane Helper Reference</title>
-!Edrivers/gpu/drm/drm_plane_helper.c
-!Pdrivers/gpu/drm/drm_plane_helper.c overview
- </sect2>
- <sect2>
- <title>Tile group</title>
-!Pdrivers/gpu/drm/drm_crtc.c Tile group
- </sect2>
- <sect2>
- <title>Bridges</title>
- <sect3>
- <title>Overview</title>
-!Pdrivers/gpu/drm/drm_bridge.c overview
- </sect3>
- <sect3>
- <title>Default bridge callback sequence</title>
-!Pdrivers/gpu/drm/drm_bridge.c bridge callbacks
- </sect3>
-!Edrivers/gpu/drm/drm_bridge.c
- </sect2>
- <sect2>
- <title>Panel Helper Reference</title>
-!Iinclude/drm/drm_panel.h
-!Edrivers/gpu/drm/drm_panel.c
-!Pdrivers/gpu/drm/drm_panel.c drm panel
- </sect2>
- </sect1>
-
- <!-- Internals: kms properties -->
-
- <sect1 id="drm-kms-properties">
- <title>KMS Properties</title>
- <para>
- Drivers may need to expose additional parameters to applications than
- those described in the previous sections. KMS supports attaching
- properties to CRTCs, connectors and planes and offers a userspace API to
- list, get and set the property values.
- </para>
- <para>
- Properties are identified by a name that uniquely defines the property
- purpose, and store an associated value. For all property types except blob
- properties the value is a 64-bit unsigned integer.
- </para>
- <para>
- KMS differentiates between properties and property instances. Drivers
- first create properties and then create and associate individual instances
- of those properties to objects. A property can be instantiated multiple
- times and associated with different objects. Values are stored in property
- instances, and all other property information are stored in the property
- and shared between all instances of the property.
- </para>
- <para>
- Every property is created with a type that influences how the KMS core
- handles the property. Supported property types are
- <variablelist>
- <varlistentry>
- <term>DRM_MODE_PROP_RANGE</term>
- <listitem><para>Range properties report their minimum and maximum
- admissible values. The KMS core verifies that values set by
- application fit in that range.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRM_MODE_PROP_ENUM</term>
- <listitem><para>Enumerated properties take a numerical value that
- ranges from 0 to the number of enumerated values defined by the
- property minus one, and associate a free-formed string name to each
- value. Applications can retrieve the list of defined value-name pairs
- and use the numerical value to get and set property instance values.
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRM_MODE_PROP_BITMASK</term>
- <listitem><para>Bitmask properties are enumeration properties that
- additionally restrict all enumerated values to the 0..63 range.
- Bitmask property instance values combine one or more of the
- enumerated bits defined by the property.</para></listitem>
- </varlistentry>
- <varlistentry>
- <term>DRM_MODE_PROP_BLOB</term>
- <listitem><para>Blob properties store a binary blob without any format
- restriction. The binary blobs are created as KMS standalone objects,
- and blob property instance values store the ID of their associated
- blob object.</para>
- <para>Blob properties are only used for the connector EDID property
- and cannot be created by drivers.</para></listitem>
- </varlistentry>
- </variablelist>
- </para>
- <para>
- To create a property drivers call one of the following functions depending
- on the property type. All property creation functions take property flags
- and name, as well as type-specific arguments.
- <itemizedlist>
- <listitem>
- <synopsis>struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
- const char *name,
- uint64_t min, uint64_t max);</synopsis>
- <para>Create a range property with the given minimum and maximum
- values.</para>
- </listitem>
- <listitem>
- <synopsis>struct drm_property *drm_property_create_enum(struct drm_device *dev, int flags,
- const char *name,
- const struct drm_prop_enum_list *props,
- int num_values);</synopsis>
- <para>Create an enumerated property. The <parameter>props</parameter>
- argument points to an array of <parameter>num_values</parameter>
- value-name pairs.</para>
- </listitem>
- <listitem>
- <synopsis>struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
- int flags, const char *name,
- const struct drm_prop_enum_list *props,
- int num_values);</synopsis>
- <para>Create a bitmask property. The <parameter>props</parameter>
- argument points to an array of <parameter>num_values</parameter>
- value-name pairs.</para>
- </listitem>
- </itemizedlist>
- </para>
- <para>
- Properties can additionally be created as immutable, in which case they
- will be read-only for applications but can be modified by the driver. To
- create an immutable property drivers must set the DRM_MODE_PROP_IMMUTABLE
- flag at property creation time.
- </para>
- <para>
- When no array of value-name pairs is readily available at property
- creation time for enumerated or range properties, drivers can create
- the property using the <function>drm_property_create</function> function
- and manually add enumeration value-name pairs by calling the
- <function>drm_property_add_enum</function> function. Care must be taken to
- properly specify the property type through the <parameter>flags</parameter>
- argument.
- </para>
- <para>
- After creating properties drivers can attach property instances to CRTC,
- connector and plane objects by calling the
- <function>drm_object_attach_property</function>. The function takes a
- pointer to the target object, a pointer to the previously created property
- and an initial instance value.
- </para>
- <sect2>
- <title>Existing KMS Properties</title>
- <para>
- The following table gives description of drm properties exposed by various
- modules/drivers.
- </para>
- <table border="1" cellpadding="0" cellspacing="0">
- <tbody>
- <tr style="font-weight: bold;">
- <td valign="top" >Owner Module/Drivers</td>
- <td valign="top" >Group</td>
- <td valign="top" >Property Name</td>
- <td valign="top" >Type</td>
- <td valign="top" >Property Values</td>
- <td valign="top" >Object attached</td>
- <td valign="top" >Description/Restrictions</td>
- </tr>
- <tr>
- <td rowspan="42" valign="top" >DRM</td>
- <td rowspan="2" valign="top" >Generic</td>
- <td valign="top" >“rotation”</td>
- <td valign="top" >BITMASK</td>
- <td valign="top" >{ 0, "rotate-0" },
- { 1, "rotate-90" },
- { 2, "rotate-180" },
- { 3, "rotate-270" },
- { 4, "reflect-x" },
- { 5, "reflect-y" }</td>
- <td valign="top" >CRTC, Plane</td>
- <td valign="top" >rotate-(degrees) rotates the image by the specified amount in degrees
- in counter clockwise direction. reflect-x and reflect-y reflects the
- image along the specified axis prior to rotation</td>
- </tr>
- <tr>
- <td valign="top" >“scaling mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >Supported by: amdgpu, gma500, i915, nouveau and radeon.</td>
- </tr>
- <tr>
- <td rowspan="5" valign="top" >Connector</td>
- <td valign="top" >“EDID”</td>
- <td valign="top" >BLOB | IMMUTABLE</td>
- <td valign="top" >0</td>
- <td valign="top" >Connector</td>
- <td valign="top" >Contains id of edid blob ptr object.</td>
- </tr>
- <tr>
- <td valign="top" >“DPMS”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ “On”, “Standby”, “Suspend”, “Off” }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >Contains DPMS operation mode value.</td>
- </tr>
- <tr>
- <td valign="top" >“PATH”</td>
- <td valign="top" >BLOB | IMMUTABLE</td>
- <td valign="top" >0</td>
- <td valign="top" >Connector</td>
- <td valign="top" >Contains topology path to a connector.</td>
- </tr>
- <tr>
- <td valign="top" >“TILE”</td>
- <td valign="top" >BLOB | IMMUTABLE</td>
- <td valign="top" >0</td>
- <td valign="top" >Connector</td>
- <td valign="top" >Contains tiling information for a connector.</td>
- </tr>
- <tr>
- <td valign="top" >“CRTC_ID”</td>
- <td valign="top" >OBJECT</td>
- <td valign="top" >DRM_MODE_OBJECT_CRTC</td>
- <td valign="top" >Connector</td>
- <td valign="top" >CRTC that connector is attached to (atomic)</td>
- </tr>
- <tr>
- <td rowspan="11" valign="top" >Plane</td>
- <td valign="top" >“type”</td>
- <td valign="top" >ENUM | IMMUTABLE</td>
- <td valign="top" >{ "Overlay", "Primary", "Cursor" }</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Plane type</td>
- </tr>
- <tr>
- <td valign="top" >“SRC_X”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout source x coordinate in 16.16 fixed point (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“SRC_Y”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout source y coordinate in 16.16 fixed point (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“SRC_W”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout source width in 16.16 fixed point (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“SRC_H”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout source height in 16.16 fixed point (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“CRTC_X”</td>
- <td valign="top" >SIGNED_RANGE</td>
- <td valign="top" >Min=INT_MIN, Max=INT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout CRTC (destination) x coordinate (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“CRTC_Y”</td>
- <td valign="top" >SIGNED_RANGE</td>
- <td valign="top" >Min=INT_MIN, Max=INT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout CRTC (destination) y coordinate (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“CRTC_W”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout CRTC (destination) width (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“CRTC_H”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout CRTC (destination) height (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“FB_ID”</td>
- <td valign="top" >OBJECT</td>
- <td valign="top" >DRM_MODE_OBJECT_FB</td>
- <td valign="top" >Plane</td>
- <td valign="top" >Scanout framebuffer (atomic)</td>
- </tr>
- <tr>
- <td valign="top" >“CRTC_ID”</td>
- <td valign="top" >OBJECT</td>
- <td valign="top" >DRM_MODE_OBJECT_CRTC</td>
- <td valign="top" >Plane</td>
- <td valign="top" >CRTC that plane is attached to (atomic)</td>
- </tr>
- <tr>
- <td rowspan="2" valign="top" >DVI-I</td>
- <td valign="top" >“subconnector”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ “Unknown”, “DVI-D”, “DVI-A” }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“select subconnector”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ “Automatic”, “DVI-D”, “DVI-A” }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="13" valign="top" >TV</td>
- <td valign="top" >“subconnector”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "Unknown", "Composite", "SVIDEO", "Component", "SCART" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“select subconnector”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "Automatic", "Composite", "SVIDEO", "Component", "SCART" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "NTSC_M", "NTSC_J", "NTSC_443", "PAL_B" } etc.</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“left margin”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“right margin”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“top margin”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“bottom margin”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“brightness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“contrast”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker reduction”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“overscan”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“saturation”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“hue”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="2" valign="top" >Virtual GPU</td>
- <td valign="top" >“suggested X”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffffff</td>
- <td valign="top" >Connector</td>
- <td valign="top" >property to suggest an X offset for a connector</td>
- </tr>
- <tr>
- <td valign="top" >“suggested Y”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffffff</td>
- <td valign="top" >Connector</td>
- <td valign="top" >property to suggest an Y offset for a connector</td>
- </tr>
- <tr>
- <td rowspan="7" valign="top" >Optional</td>
- <td valign="top" >"aspect ratio"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "None", "4:3", "16:9" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TDB</td>
- </tr>
- <tr>
- <td valign="top" >“dirty”</td>
- <td valign="top" >ENUM | IMMUTABLE</td>
- <td valign="top" >{ "Off", "On", "Annotate" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“DEGAMMA_LUT”</td>
- <td valign="top" >BLOB</td>
- <td valign="top" >0</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >DRM property to set the degamma lookup table
- (LUT) mapping pixel data from the framebuffer before it is
- given to the transformation matrix. The data is an interpreted
- as an array of struct drm_color_lut elements. Hardware might
- choose not to use the full precision of the LUT elements nor
- use all the elements of the LUT (for example the hardware
- might choose to interpolate between LUT[0] and LUT[4]). </td>
- </tr>
- <tr>
- <td valign="top" >“DEGAMMA_LUT_SIZE”</td>
- <td valign="top" >RANGE | IMMUTABLE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >DRM property to gives the size of the lookup
- table to be set on the DEGAMMA_LUT property (the size depends
- on the underlying hardware).</td>
- </tr>
- <tr>
- <td valign="top" >“CTM”</td>
- <td valign="top" >BLOB</td>
- <td valign="top" >0</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >DRM property to set the current
- transformation matrix (CTM) apply to pixel data after the
- lookup through the degamma LUT and before the lookup through
- the gamma LUT. The data is an interpreted as a struct
- drm_color_ctm.</td>
- </tr>
- <tr>
- <td valign="top" >“GAMMA_LUT”</td>
- <td valign="top" >BLOB</td>
- <td valign="top" >0</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >DRM property to set the gamma lookup table
- (LUT) mapping pixel data after to the transformation matrix to
- data sent to the connector. The data is an interpreted as an
- array of struct drm_color_lut elements. Hardware might choose
- not to use the full precision of the LUT elements nor use all
- the elements of the LUT (for example the hardware might choose
- to interpolate between LUT[0] and LUT[4]).</td>
- </tr>
- <tr>
- <td valign="top" >“GAMMA_LUT_SIZE”</td>
- <td valign="top" >RANGE | IMMUTABLE</td>
- <td valign="top" >Min=0, Max=UINT_MAX</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >DRM property to gives the size of the lookup
- table to be set on the GAMMA_LUT property (the size depends on
- the underlying hardware).</td>
- </tr>
- <tr>
- <td rowspan="20" valign="top" >i915</td>
- <td rowspan="2" valign="top" >Generic</td>
- <td valign="top" >"Broadcast RGB"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "Automatic", "Full", "Limited 16:235" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >When this property is set to Limited 16:235
- and CTM is set, the hardware will be programmed with the
- result of the multiplication of CTM by the limited range
- matrix to ensure the pixels normaly in the range 0..1.0 are
- remapped to the range 16/255..235/255.</td>
- </tr>
- <tr>
- <td valign="top" >“audio”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "force-dvi", "off", "auto", "on" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="17" valign="top" >SDVO-TV</td>
- <td valign="top" >“mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "NTSC_M", "NTSC_J", "NTSC_443", "PAL_B" } etc.</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"left_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"right_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"top_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"bottom_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“hpos”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“vpos”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“contrast”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“saturation”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“hue”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“sharpness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker_filter”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker_filter_adaptive”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker_filter_2d”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“tv_chroma_filter”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“tv_luma_filter”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“dot_crawl”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >SDVO-TV/LVDS</td>
- <td valign="top" >“brightness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="2" valign="top" >CDV gma-500</td>
- <td rowspan="2" valign="top" >Generic</td>
- <td valign="top" >"Broadcast RGB"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ “Full”, “Limited 16:235” }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"Broadcast RGB"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ “off”, “auto”, “on” }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="19" valign="top" >Poulsbo</td>
- <td rowspan="1" valign="top" >Generic</td>
- <td valign="top" >“backlight”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=100</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="17" valign="top" >SDVO-TV</td>
- <td valign="top" >“mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "NTSC_M", "NTSC_J", "NTSC_443", "PAL_B" } etc.</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"left_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"right_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"top_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"bottom_margin"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“hpos”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“vpos”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“contrast”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“saturation”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“hue”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“sharpness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker_filter”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker_filter_adaptive”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“flicker_filter_2d”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“tv_chroma_filter”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“tv_luma_filter”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“dot_crawl”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >SDVO-TV/LVDS</td>
- <td valign="top" >“brightness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max= SDVO dependent</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="11" valign="top" >armada</td>
- <td rowspan="2" valign="top" >CRTC</td>
- <td valign="top" >"CSC_YUV"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "Auto" , "CCIR601", "CCIR709" }</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"CSC_RGB"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "Auto", "Computer system", "Studio" }</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="9" valign="top" >Overlay</td>
- <td valign="top" >"colorkey"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"colorkey_min"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"colorkey_max"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"colorkey_val"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"colorkey_alpha"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0xffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"colorkey_mode"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "disabled", "Y component", "U component"
- , "V component", "RGB", “R component", "G component", "B component" }</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"brightness"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=256 + 255</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"contrast"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0x7fff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"saturation"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0x7fff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="2" valign="top" >exynos</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >“mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "normal", "blank" }</td>
- <td valign="top" >CRTC</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >Overlay</td>
- <td valign="top" >“zpos”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=MAX_PLANE-1</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="2" valign="top" >i2c/ch7006_drv</td>
- <td valign="top" >Generic</td>
- <td valign="top" >“scale”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=2</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="1" valign="top" >TV</td>
- <td valign="top" >“mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "PAL", "PAL-M","PAL-N"}, ”PAL-Nc"
- , "PAL-60", "NTSC-M", "NTSC-J" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="15" valign="top" >nouveau</td>
- <td rowspan="6" valign="top" >NV10 Overlay</td>
- <td valign="top" >"colorkey"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0x01ffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“contrast”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=8192-1</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“brightness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1024</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“hue”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=359</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“saturation”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=8192-1</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“iturbt_709”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="2" valign="top" >Nv04 Overlay</td>
- <td valign="top" >“colorkey”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0x01ffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“brightness”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1024</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="7" valign="top" >Display</td>
- <td valign="top" >“dithering mode”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "auto", "off", "on" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“dithering depth”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "auto", "off", "on", "static 2x2", "dynamic 2x2", "temporal" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“underscan”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "auto", "6 bpc", "8 bpc" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“underscan hborder”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=128</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“underscan vborder”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=128</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“vibrant hue”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=180</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >“color vibrance”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=200</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >omap</td>
- <td valign="top" >Generic</td>
- <td valign="top" >“zorder”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=3</td>
- <td valign="top" >CRTC, Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >qxl</td>
- <td valign="top" >Generic</td>
- <td valign="top" >“hotplug_mode_update"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="9" valign="top" >radeon</td>
- <td valign="top" >DVI-I</td>
- <td valign="top" >“coherent”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >DAC enable load detect</td>
- <td valign="top" >“load detection”</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=1</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >TV Standard</td>
- <td valign="top" >"tv standard"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "ntsc", "pal", "pal-m", "pal-60", "ntsc-j"
- , "scart-pal", "pal-cn", "secam" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >legacy TMDS PLL detect</td>
- <td valign="top" >"tmds_pll"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "driver", "bios" }</td>
- <td valign="top" >-</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="3" valign="top" >Underscan</td>
- <td valign="top" >"underscan"</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "off", "on", "auto" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"underscan hborder"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=128</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"underscan vborder"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=128</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >Audio</td>
- <td valign="top" >“audio”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "off", "on", "auto" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >FMT Dithering</td>
- <td valign="top" >“dither”</td>
- <td valign="top" >ENUM</td>
- <td valign="top" >{ "off", "on" }</td>
- <td valign="top" >Connector</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td rowspan="3" valign="top" >rcar-du</td>
- <td rowspan="3" valign="top" >Generic</td>
- <td valign="top" >"alpha"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=255</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"colorkey"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=0, Max=0x01ffffff</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- <tr>
- <td valign="top" >"zpos"</td>
- <td valign="top" >RANGE</td>
- <td valign="top" >Min=1, Max=7</td>
- <td valign="top" >Plane</td>
- <td valign="top" >TBD</td>
- </tr>
- </tbody>
- </table>
- </sect2>
- </sect1>
-
- <!-- Internals: vertical blanking -->
-
- <sect1 id="drm-vertical-blank">
- <title>Vertical Blanking</title>
- <para>
- Vertical blanking plays a major role in graphics rendering. To achieve
- tear-free display, users must synchronize page flips and/or rendering to
- vertical blanking. The DRM API offers ioctls to perform page flips
- synchronized to vertical blanking and wait for vertical blanking.
- </para>
- <para>
- The DRM core handles most of the vertical blanking management logic, which
- involves filtering out spurious interrupts, keeping race-free blanking
- counters, coping with counter wrap-around and resets and keeping use
- counts. It relies on the driver to generate vertical blanking interrupts
- and optionally provide a hardware vertical blanking counter. Drivers must
- implement the following operations.
- </para>
- <itemizedlist>
- <listitem>
- <synopsis>int (*enable_vblank) (struct drm_device *dev, int crtc);
-void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis>
- <para>
- Enable or disable vertical blanking interrupts for the given CRTC.
- </para>
- </listitem>
- <listitem>
- <synopsis>u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);</synopsis>
- <para>
- Retrieve the value of the vertical blanking counter for the given
- CRTC. If the hardware maintains a vertical blanking counter its value
- should be returned. Otherwise drivers can use the
- <function>drm_vblank_count</function> helper function to handle this
- operation.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- Drivers must initialize the vertical blanking handling core with a call to
- <function>drm_vblank_init</function> in their
- <methodname>load</methodname> operation. The function will set the struct
- <structname>drm_device</structname>
- <structfield>vblank_disable_allowed</structfield> field to 0. This will
- keep vertical blanking interrupts enabled permanently until the first mode
- set operation, where <structfield>vblank_disable_allowed</structfield> is
- set to 1. The reason behind this is not clear. Drivers can set the field
- to 1 after <function>calling drm_vblank_init</function> to make vertical
- blanking interrupts dynamically managed from the beginning.
- </para>
- <para>
- Vertical blanking interrupts can be enabled by the DRM core or by drivers
- themselves (for instance to handle page flipping operations). The DRM core
- maintains a vertical blanking use count to ensure that the interrupts are
- not disabled while a user still needs them. To increment the use count,
- drivers call <function>drm_vblank_get</function>. Upon return vertical
- blanking interrupts are guaranteed to be enabled.
- </para>
- <para>
- To decrement the use count drivers call
- <function>drm_vblank_put</function>. Only when the use count drops to zero
- will the DRM core disable the vertical blanking interrupts after a delay
- by scheduling a timer. The delay is accessible through the vblankoffdelay
- module parameter or the <varname>drm_vblank_offdelay</varname> global
- variable and expressed in milliseconds. Its default value is 5000 ms.
- Zero means never disable, and a negative value means disable immediately.
- Drivers may override the behaviour by setting the
- <structname>drm_device</structname>
- <structfield>vblank_disable_immediate</structfield> flag, which when set
- causes vblank interrupts to be disabled immediately regardless of the
- drm_vblank_offdelay value. The flag should only be set if there's a
- properly working hardware vblank counter present.
- </para>
- <para>
- When a vertical blanking interrupt occurs drivers only need to call the
- <function>drm_handle_vblank</function> function to account for the
- interrupt.
- </para>
- <para>
- Resources allocated by <function>drm_vblank_init</function> must be freed
- with a call to <function>drm_vblank_cleanup</function> in the driver
- <methodname>unload</methodname> operation handler.
- </para>
- <sect2>
- <title>Vertical Blanking and Interrupt Handling Functions Reference</title>
-!Edrivers/gpu/drm/drm_irq.c
-!Finclude/drm/drmP.h drm_crtc_vblank_waitqueue
- </sect2>
- </sect1>
-
- <!-- Internals: open/close, file operations and ioctls -->
-
- <sect1>
- <title>Open/Close, File Operations and IOCTLs</title>
- <sect2>
- <title>Open and Close</title>
- <synopsis>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 *);</synopsis>
- <abstract>Open and close handlers. None of those methods are mandatory.
- </abstract>
- <para>
- The <methodname>firstopen</methodname> 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 <methodname>load</methodname>
- method instead.
- </para>
- <para>
- Similarly the <methodname>lastclose</methodname> 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 <methodname>firstopen</methodname> and
- <methodname>lastclose</methodname> calls can thus be unbalanced.
- </para>
- <para>
- The <methodname>open</methodname> 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
- <structname>drm_file</structname> <structfield>driver_priv</structfield>
- field. Note that the <methodname>open</methodname> method is called
- before <methodname>firstopen</methodname>.
- </para>
- <para>
- The close operation is split into <methodname>preclose</methodname> and
- <methodname>postclose</methodname> methods. Drivers must stop and
- cleanup all per-file operations in the <methodname>preclose</methodname>
- 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 <methodname>preclose</methodname> method.
- </para>
- <para>
- Finally the <methodname>postclose</methodname> method is called as the
- last step of the close operation, right before calling the
- <methodname>lastclose</methodname> method if no other open file handle
- exists for the device. Drivers that have allocated per-file private data
- in the <methodname>open</methodname> method should free it here.
- </para>
- <para>
- The <methodname>lastclose</methodname> 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 vga_switcheroo infrastructure (see
- <xref linkend="vga_switcheroo"/>). 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.
- </para>
- </sect2>
- <sect2>
- <title>File Operations</title>
-!Pdrivers/gpu/drm/drm_fops.c file operations
-!Edrivers/gpu/drm/drm_fops.c
- </sect2>
- <sect2>
- <title>IOCTLs</title>
- <synopsis>struct drm_ioctl_desc *ioctls;
-int num_ioctls;</synopsis>
- <abstract>Driver-specific ioctls descriptors table.</abstract>
- <para>
- 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.
- </para>
- <para>
- <programlisting>DRM_IOCTL_DEF_DRV(ioctl, func, flags)</programlisting>
- <para>
- <parameter>ioctl</parameter> 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.
- </para>
- <para>
- <parameter>func</parameter> is a pointer to the ioctl handler function
- compatible with the <type>drm_ioctl_t</type> type.
- <programlisting>typedef int drm_ioctl_t(struct drm_device *dev, void *data,
- struct drm_file *file_priv);</programlisting>
- </para>
- <para>
- <parameter>flags</parameter> is a bitmask combination of the following
- values. It restricts how the ioctl is allowed to be called.
- <itemizedlist>
- <listitem><para>
- DRM_AUTH - Only authenticated callers allowed
- </para></listitem>
- <listitem><para>
- DRM_MASTER - The ioctl can only be called on the master file
- handle
- </para></listitem>
- <listitem><para>
- DRM_ROOT_ONLY - Only callers with the SYSADMIN capability allowed
- </para></listitem>
- <listitem><para>
- DRM_CONTROL_ALLOW - The ioctl can only be called on a control
- device
- </para></listitem>
- <listitem><para>
- 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.
- </para></listitem>
- </itemizedlist>
- </para>
- </para>
-!Edrivers/gpu/drm/drm_ioctl.c
- </sect2>
- </sect1>
- <sect1>
- <title>Legacy Support Code</title>
- <para>
- 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.
- </para>
-
- <sect2>
- <title>Legacy Suspend/Resume</title>
- <para>
- 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.
- </para>
- <synopsis>int (*suspend) (struct drm_device *, pm_message_t state);
- int (*resume) (struct drm_device *);</synopsis>
- <para>
- Those are legacy suspend and resume methods which
- <emphasis>only</emphasis> 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 struct <structname>device_driver</structname> dev_pm_ops) and set
- these methods to NULL.
- </para>
- </sect2>
-
- <sect2>
- <title>Legacy DMA Services</title>
- <para>
- This should cover how DMA mapping etc. is supported by the core.
- These functions are deprecated and should not be used.
- </para>
- </sect2>
- </sect1>
- </chapter>
-
-<!-- TODO
-
-- Add a glossary
-- Document the struct_mutex catch-all lock
-- Document connector properties
-
-- Why is the load method optional?
-- What are drivers supposed to set the initial display state to, and how?
- Connector's DPMS states are not initialized and are thus equal to
- DRM_MODE_DPMS_ON. The fbcon compatibility layer calls
- drm_helper_disable_unused_functions(), which disables unused encoders and
- CRTCs, but doesn't touch the connectors' DPMS state, and
- drm_helper_connector_dpms() in reaction to fbdev blanking events. Do drivers
- that don't implement (or just don't use) fbcon compatibility need to call
- those functions themselves?
-- KMS drivers must call drm_vblank_pre_modeset() and drm_vblank_post_modeset()
- around mode setting. Should this be done in the DRM core?
-- vblank_disable_allowed is set to 1 in the first drm_vblank_post_modeset()
- call and never set back to 0. It seems to be safe to permanently set it to 1
- in drm_vblank_init() for KMS driver, and it might be safe for UMS drivers as
- well. This should be investigated.
-- crtc and connector .save and .restore operations are only used internally in
- drivers, should they be removed from the core?
-- encoder mid-layer .save and .restore operations are only used internally in
- drivers, should they be removed from the core?
-- encoder mid-layer .detect operation is only used internally in drivers,
- should it be removed from the core?
--->
-
- <!-- External interfaces -->
-
- <chapter id="drmExternals">
- <title>Userland interfaces</title>
- <para>
- The DRM core exports several interfaces to applications,
- generally intended to be used through corresponding libdrm
- wrapper functions. In addition, drivers export device-specific
- interfaces for use by userspace drivers &amp; device-aware
- applications through ioctls and sysfs files.
- </para>
- <para>
- External interfaces include: memory mapping, context management,
- DMA operations, AGP management, vblank control, fence
- management, memory management, and output management.
- </para>
- <para>
- Cover generic ioctls and sysfs layout here. We only need high-level
- info, since man pages should cover the rest.
- </para>
-
- <!-- External: render nodes -->
-
- <sect1>
- <title>Render nodes</title>
- <para>
- DRM core provides multiple character-devices for user-space to use.
- Depending on which device is opened, user-space can perform a different
- set of operations (mainly ioctls). The primary node is always created
- and called card&lt;num&gt;. Additionally, a currently
- unused control node, called controlD&lt;num&gt; is also
- created. The primary node provides all legacy operations and
- historically was the only interface used by userspace. With KMS, the
- control node was introduced. However, the planned KMS control interface
- has never been written and so the control node stays unused to date.
- </para>
- <para>
- With the increased use of offscreen renderers and GPGPU applications,
- clients no longer require running compositors or graphics servers to
- make use of a GPU. But the DRM API required unprivileged clients to
- authenticate to a DRM-Master prior to getting GPU access. To avoid this
- step and to grant clients GPU access without authenticating, render
- nodes were introduced. Render nodes solely serve render clients, that
- is, no modesetting or privileged ioctls can be issued on render nodes.
- Only non-global rendering commands are allowed. If a driver supports
- render nodes, it must advertise it via the DRIVER_RENDER
- DRM driver capability. If not supported, the primary node must be used
- for render clients together with the legacy drmAuth authentication
- procedure.
- </para>
- <para>
- If a driver advertises render node support, DRM core will create a
- separate render node called renderD&lt;num&gt;. There will
- be one render node per device. No ioctls except PRIME-related ioctls
- will be allowed on this node. Especially GEM_OPEN will be
- explicitly prohibited. Render nodes are designed to avoid the
- buffer-leaks, which occur if clients guess the flink names or mmap
- offsets on the legacy interface. Additionally to this basic interface,
- drivers must mark their driver-dependent render-only ioctls as
- DRM_RENDER_ALLOW so render clients can use them. Driver
- authors must be careful not to allow any privileged ioctls on render
- nodes.
- </para>
- <para>
- With render nodes, user-space can now control access to the render node
- via basic file-system access-modes. A running graphics server which
- authenticates clients on the privileged primary/legacy node is no longer
- required. Instead, a client can open the render node and is immediately
- granted GPU access. Communication between clients (or servers) is done
- via PRIME. FLINK from render node to legacy node is not supported. New
- clients must not use the insecure FLINK interface.
- </para>
- <para>
- Besides dropping all modeset/global ioctls, render nodes also drop the
- DRM-Master concept. There is no reason to associate render clients with
- a DRM-Master as they are independent of any graphics server. Besides,
- they must work without any running master, anyway.
- Drivers must be able to run without a master object if they support
- render nodes. If, on the other hand, a driver requires shared state
- between clients which is visible to user-space and accessible beyond
- open-file boundaries, they cannot support render nodes.
- </para>
- </sect1>
-
- <!-- External: vblank handling -->
-
- <sect1>
- <title>VBlank event handling</title>
- <para>
- The DRM core exposes two vertical blank related ioctls:
- <variablelist>
- <varlistentry>
- <term>DRM_IOCTL_WAIT_VBLANK</term>
- <listitem>
- <para>
- This takes a struct drm_wait_vblank structure as its argument,
- and it is used to block or request a signal when a specified
- vblank event occurs.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>DRM_IOCTL_MODESET_CTL</term>
- <listitem>
- <para>
- This was only used for user-mode-settind drivers around
- modesetting changes to allow the kernel to update the vblank
- interrupt after mode setting, since on many devices the vertical
- blank counter is reset to 0 at some point during modeset. Modern
- drivers should not call this any more since with kernel mode
- setting it is a no-op.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </para>
- </sect1>
-
- </chapter>
-</part>
-<part id="drmDrivers">
- <title>DRM Drivers</title>
-
- <partintro>
- <para>
- This second part of the GPU Driver Developer's Guide documents driver
- code, implementation details and also all the driver-specific userspace
- interfaces. Especially since all hardware-acceleration interfaces to
- userspace are driver specific for efficiency and other reasons these
- interfaces can be rather substantial. Hence every driver has its own
- chapter.
- </para>
- </partintro>
-
- <chapter id="drmI915">
- <title>drm/i915 Intel GFX Driver</title>
- <para>
- The drm/i915 driver supports all (with the exception of some very early
- models) integrated GFX chipsets with both Intel display and rendering
- blocks. This excludes a set of SoC platforms with an SGX rendering unit,
- those have basic support through the gma500 drm driver.
- </para>
- <sect1>
- <title>Core Driver Infrastructure</title>
- <para>
- This section covers core driver infrastructure used by both the display
- and the GEM parts of the driver.
- </para>
- <sect2>
- <title>Runtime Power Management</title>
-!Pdrivers/gpu/drm/i915/intel_runtime_pm.c runtime pm
-!Idrivers/gpu/drm/i915/intel_runtime_pm.c
-!Idrivers/gpu/drm/i915/intel_uncore.c
- </sect2>
- <sect2>
- <title>Interrupt Handling</title>
-!Pdrivers/gpu/drm/i915/i915_irq.c interrupt handling
-!Fdrivers/gpu/drm/i915/i915_irq.c intel_irq_init intel_irq_init_hw intel_hpd_init
-!Fdrivers/gpu/drm/i915/i915_irq.c intel_runtime_pm_disable_interrupts
-!Fdrivers/gpu/drm/i915/i915_irq.c intel_runtime_pm_enable_interrupts
- </sect2>
- <sect2>
- <title>Intel GVT-g Guest Support(vGPU)</title>
-!Pdrivers/gpu/drm/i915/i915_vgpu.c Intel GVT-g guest support
-!Idrivers/gpu/drm/i915/i915_vgpu.c
- </sect2>
- </sect1>
- <sect1>
- <title>Display Hardware Handling</title>
- <para>
- This section covers everything related to the display hardware including
- the mode setting infrastructure, plane, sprite and cursor handling and
- display, output probing and related topics.
- </para>
- <sect2>
- <title>Mode Setting Infrastructure</title>
- <para>
- The i915 driver is thus far the only DRM driver which doesn't use the
- common DRM helper code to implement mode setting sequences. Thus it
- has its own tailor-made infrastructure for executing a display
- configuration change.
- </para>
- </sect2>
- <sect2>
- <title>Frontbuffer Tracking</title>
-!Pdrivers/gpu/drm/i915/intel_frontbuffer.c frontbuffer tracking
-!Idrivers/gpu/drm/i915/intel_frontbuffer.c
-!Fdrivers/gpu/drm/i915/i915_gem.c i915_gem_track_fb
- </sect2>
- <sect2>
- <title>Display FIFO Underrun Reporting</title>
-!Pdrivers/gpu/drm/i915/intel_fifo_underrun.c fifo underrun handling
-!Idrivers/gpu/drm/i915/intel_fifo_underrun.c
- </sect2>
- <sect2>
- <title>Plane Configuration</title>
- <para>
- This section covers plane configuration and composition with the
- primary plane, sprites, cursors and overlays. This includes the
- infrastructure to do atomic vsync'ed updates of all this state and
- also tightly coupled topics like watermark setup and computation,
- framebuffer compression and panel self refresh.
- </para>
- </sect2>
- <sect2>
- <title>Atomic Plane Helpers</title>
-!Pdrivers/gpu/drm/i915/intel_atomic_plane.c atomic plane helpers
-!Idrivers/gpu/drm/i915/intel_atomic_plane.c
- </sect2>
- <sect2>
- <title>Output Probing</title>
- <para>
- This section covers output probing and related infrastructure like the
- hotplug interrupt storm detection and mitigation code. Note that the
- i915 driver still uses most of the common DRM helper code for output
- probing, so those sections fully apply.
- </para>
- </sect2>
- <sect2>
- <title>Hotplug</title>
-!Pdrivers/gpu/drm/i915/intel_hotplug.c Hotplug
-!Idrivers/gpu/drm/i915/intel_hotplug.c
- </sect2>
- <sect2>
- <title>High Definition Audio</title>
-!Pdrivers/gpu/drm/i915/intel_audio.c High Definition Audio over HDMI and Display Port
-!Idrivers/gpu/drm/i915/intel_audio.c
-!Iinclude/drm/i915_component.h
- </sect2>
- <sect2>
- <title>Panel Self Refresh PSR (PSR/SRD)</title>
-!Pdrivers/gpu/drm/i915/intel_psr.c Panel Self Refresh (PSR/SRD)
-!Idrivers/gpu/drm/i915/intel_psr.c
- </sect2>
- <sect2>
- <title>Frame Buffer Compression (FBC)</title>
-!Pdrivers/gpu/drm/i915/intel_fbc.c Frame Buffer Compression (FBC)
-!Idrivers/gpu/drm/i915/intel_fbc.c
- </sect2>
- <sect2>
- <title>Display Refresh Rate Switching (DRRS)</title>
-!Pdrivers/gpu/drm/i915/intel_dp.c Display Refresh Rate Switching (DRRS)
-!Fdrivers/gpu/drm/i915/intel_dp.c intel_dp_set_drrs_state
-!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_enable
-!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_disable
-!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_invalidate
-!Fdrivers/gpu/drm/i915/intel_dp.c intel_edp_drrs_flush
-!Fdrivers/gpu/drm/i915/intel_dp.c intel_dp_drrs_init
-
- </sect2>
- <sect2>
- <title>DPIO</title>
-!Pdrivers/gpu/drm/i915/i915_reg.h DPIO
- </sect2>
-
- <sect2>
- <title>CSR firmware support for DMC</title>
-!Pdrivers/gpu/drm/i915/intel_csr.c csr support for dmc
-!Idrivers/gpu/drm/i915/intel_csr.c
- </sect2>
- <sect2>
- <title>Video BIOS Table (VBT)</title>
-!Pdrivers/gpu/drm/i915/intel_bios.c Video BIOS Table (VBT)
-!Idrivers/gpu/drm/i915/intel_bios.c
-!Idrivers/gpu/drm/i915/intel_vbt_defs.h
- </sect2>
- </sect1>
-
- <sect1>
- <title>Memory Management and Command Submission</title>
- <para>
- This sections covers all things related to the GEM implementation in the
- i915 driver.
- </para>
- <sect2>
- <title>Batchbuffer Parsing</title>
-!Pdrivers/gpu/drm/i915/i915_cmd_parser.c batch buffer command parser
-!Idrivers/gpu/drm/i915/i915_cmd_parser.c
- </sect2>
- <sect2>
- <title>Batchbuffer Pools</title>
-!Pdrivers/gpu/drm/i915/i915_gem_batch_pool.c batch pool
-!Idrivers/gpu/drm/i915/i915_gem_batch_pool.c
- </sect2>
- <sect2>
- <title>Logical Rings, Logical Ring Contexts and Execlists</title>
-!Pdrivers/gpu/drm/i915/intel_lrc.c Logical Rings, Logical Ring Contexts and Execlists
-!Idrivers/gpu/drm/i915/intel_lrc.c
- </sect2>
- <sect2>
- <title>Global GTT views</title>
-!Pdrivers/gpu/drm/i915/i915_gem_gtt.c Global GTT views
-!Idrivers/gpu/drm/i915/i915_gem_gtt.c
- </sect2>
- <sect2>
- <title>GTT Fences and Swizzling</title>
-!Idrivers/gpu/drm/i915/i915_gem_fence.c
- <sect3>
- <title>Global GTT Fence Handling</title>
-!Pdrivers/gpu/drm/i915/i915_gem_fence.c fence register handling
- </sect3>
- <sect3>
- <title>Hardware Tiling and Swizzling Details</title>
-!Pdrivers/gpu/drm/i915/i915_gem_fence.c tiling swizzling details
- </sect3>
- </sect2>
- <sect2>
- <title>Object Tiling IOCTLs</title>
-!Idrivers/gpu/drm/i915/i915_gem_tiling.c
-!Pdrivers/gpu/drm/i915/i915_gem_tiling.c buffer object tiling
- </sect2>
- <sect2>
- <title>Buffer Object Eviction</title>
- <para>
- This section documents the interface functions for evicting buffer
- objects to make space available in the virtual gpu address spaces.
- Note that this is mostly orthogonal to shrinking buffer objects
- caches, which has the goal to make main memory (shared with the gpu
- through the unified memory architecture) available.
- </para>
-!Idrivers/gpu/drm/i915/i915_gem_evict.c
- </sect2>
- <sect2>
- <title>Buffer Object Memory Shrinking</title>
- <para>
- This section documents the interface function for shrinking memory
- usage of buffer object caches. Shrinking is used to make main memory
- available. Note that this is mostly orthogonal to evicting buffer
- objects, which has the goal to make space in gpu virtual address
- spaces.
- </para>
-!Idrivers/gpu/drm/i915/i915_gem_shrinker.c
- </sect2>
- </sect1>
- <sect1>
- <title>GuC</title>
- <sect2>
- <title>GuC-specific firmware loader</title>
-!Pdrivers/gpu/drm/i915/intel_guc_loader.c GuC-specific firmware loader
-!Idrivers/gpu/drm/i915/intel_guc_loader.c
- </sect2>
- <sect2>
- <title>GuC-based command submission</title>
-!Pdrivers/gpu/drm/i915/i915_guc_submission.c GuC-based command submission
-!Idrivers/gpu/drm/i915/i915_guc_submission.c
- </sect2>
- <sect2>
- <title>GuC Firmware Layout</title>
-!Pdrivers/gpu/drm/i915/intel_guc_fwif.h GuC Firmware Layout
- </sect2>
- </sect1>
-
- <sect1>
- <title> Tracing </title>
- <para>
- This sections covers all things related to the tracepoints implemented in
- the i915 driver.
- </para>
- <sect2>
- <title> i915_ppgtt_create and i915_ppgtt_release </title>
-!Pdrivers/gpu/drm/i915/i915_trace.h i915_ppgtt_create and i915_ppgtt_release tracepoints
- </sect2>
- <sect2>
- <title> i915_context_create and i915_context_free </title>
-!Pdrivers/gpu/drm/i915/i915_trace.h i915_context_create and i915_context_free tracepoints
- </sect2>
- <sect2>
- <title> switch_mm </title>
-!Pdrivers/gpu/drm/i915/i915_trace.h switch_mm tracepoint
- </sect2>
- </sect1>
-
- </chapter>
-!Cdrivers/gpu/drm/i915/i915_irq.c
-</part>
-
-<part id="vga_switcheroo">
- <title>vga_switcheroo</title>
- <partintro>
-!Pdrivers/gpu/vga/vga_switcheroo.c Overview
- </partintro>
-
- <chapter id="modes_of_use">
- <title>Modes of Use</title>
- <sect1>
- <title>Manual switching and manual power control</title>
-!Pdrivers/gpu/vga/vga_switcheroo.c Manual switching and manual power control
- </sect1>
- <sect1>
- <title>Driver power control</title>
-!Pdrivers/gpu/vga/vga_switcheroo.c Driver power control
- </sect1>
- </chapter>
-
- <chapter id="api">
- <title>API</title>
- <sect1>
- <title>Public functions</title>
-!Edrivers/gpu/vga/vga_switcheroo.c
- </sect1>
- <sect1>
- <title>Public structures</title>
-!Finclude/linux/vga_switcheroo.h vga_switcheroo_handler
-!Finclude/linux/vga_switcheroo.h vga_switcheroo_client_ops
- </sect1>
- <sect1>
- <title>Public constants</title>
-!Finclude/linux/vga_switcheroo.h vga_switcheroo_handler_flags_t
-!Finclude/linux/vga_switcheroo.h vga_switcheroo_client_id
-!Finclude/linux/vga_switcheroo.h vga_switcheroo_state
- </sect1>
- <sect1>
- <title>Private structures</title>
-!Fdrivers/gpu/vga/vga_switcheroo.c vgasr_priv
-!Fdrivers/gpu/vga/vga_switcheroo.c vga_switcheroo_client
- </sect1>
- </chapter>
-
- <chapter id="handlers">
- <title>Handlers</title>
- <sect1>
- <title>apple-gmux Handler</title>
-!Pdrivers/platform/x86/apple-gmux.c Overview
-!Pdrivers/platform/x86/apple-gmux.c Interrupt
- <sect2>
- <title>Graphics mux</title>
-!Pdrivers/platform/x86/apple-gmux.c Graphics mux
- </sect2>
- <sect2>
- <title>Power control</title>
-!Pdrivers/platform/x86/apple-gmux.c Power control
- </sect2>
- <sect2>
- <title>Backlight control</title>
-!Pdrivers/platform/x86/apple-gmux.c Backlight control
- </sect2>
- <sect2>
- <title>Public functions</title>
-!Iinclude/linux/apple-gmux.h
- </sect2>
- </sect1>
- </chapter>
-
-!Cdrivers/gpu/vga/vga_switcheroo.c
-!Cinclude/linux/vga_switcheroo.h
-!Cdrivers/platform/x86/apple-gmux.c
-</part>
-
-</book>