163 lines
8.9 KiB
ReStructuredText
163 lines
8.9 KiB
ReStructuredText
|
====================
|
||
|
DC Programming Model
|
||
|
====================
|
||
|
|
||
|
In the :ref:`Display Core Next (DCN) <dcn_overview>` and :ref:`DCN Block
|
||
|
<dcn_blocks>` pages, you learned about the hardware components and how they
|
||
|
interact with each other. On this page, the focus is shifted to the display
|
||
|
code architecture. Hence, it is reasonable to remind the reader that the code
|
||
|
in DC is shared with other OSes; for this reason, DC provides a set of
|
||
|
abstractions and operations to connect different APIs with the hardware
|
||
|
configuration. See DC as a service available for a Display Manager (amdgpu_dm)
|
||
|
to access and configure DCN/DCE hardware (DCE is also part of DC, but for
|
||
|
simplicity's sake, this documentation only examines DCN).
|
||
|
|
||
|
.. note::
|
||
|
For this page, we will use the term GPU to refers to dGPU and APU.
|
||
|
|
||
|
Overview
|
||
|
========
|
||
|
|
||
|
From the display hardware perspective, it is plausible to expect that if a
|
||
|
problem is well-defined, it will probably be implemented at the hardware level.
|
||
|
On the other hand, when there are multiple ways of achieving something without
|
||
|
a very well-defined scope, the solution is usually implemented as a policy at
|
||
|
the DC level. In other words, some policies are defined in the DC core
|
||
|
(resource management, power optimization, image quality, etc.), and the others
|
||
|
implemented in hardware are enabled via DC configuration.
|
||
|
|
||
|
In terms of hardware management, DCN has multiple instances of the same block
|
||
|
(e.g., HUBP, DPP, MPC, etc), and during the driver execution, it might be
|
||
|
necessary to use some of these instances. The core has policies in place for
|
||
|
handling those instances. Regarding resource management, the DC objective is
|
||
|
quite simple: minimize the hardware shuffle when the driver performs some
|
||
|
actions. When the state changes from A to B, the transition is considered
|
||
|
easier to maneuver if the hardware resource is still used for the same set of
|
||
|
driver objects. Usually, adding and removing a resource to a `pipe_ctx` (more
|
||
|
details below) is not a problem; however, moving a resource from one `pipe_ctx`
|
||
|
to another should be avoided.
|
||
|
|
||
|
Another area of influence for DC is power optimization, which has a myriad of
|
||
|
arrangement possibilities. In some way, just displaying an image via DCN should
|
||
|
be relatively straightforward; however, showing it with the best power
|
||
|
footprint is more desirable, but it has many associated challenges.
|
||
|
Unfortunately, there is no straight-forward analytic way to determine if a
|
||
|
configuration is the best one for the context due to the enormous variety of
|
||
|
variables related to this problem (e.g., many different DCN/DCE hardware
|
||
|
versions, different displays configurations, etc.) for this reason DC
|
||
|
implements a dedicated library for trying some configuration and verify if it
|
||
|
is possible to support it or not. This type of policy is extremely complex to
|
||
|
create and maintain, and amdgpu driver relies on Display Mode Library (DML) to
|
||
|
generate the best decisions.
|
||
|
|
||
|
In summary, DC must deal with the complexity of handling multiple scenarios and
|
||
|
determine policies to manage them. All of the above information is conveyed to
|
||
|
give the reader some idea about the complexity of driving a display from the
|
||
|
driver's perspective. This page hopes to allow the reader to better navigate
|
||
|
over the amdgpu display code.
|
||
|
|
||
|
Display Driver Architecture Overview
|
||
|
====================================
|
||
|
|
||
|
The diagram below provides an overview of the display driver architecture;
|
||
|
notice it illustrates the software layers adopted by DC:
|
||
|
|
||
|
.. kernel-figure:: dc-components.svg
|
||
|
|
||
|
The first layer of the diagram is the high-level DC API represented by the
|
||
|
`dc.h` file; below it are two big blocks represented by Core and Link. Next is
|
||
|
the hardware configuration block; the main file describing it is
|
||
|
the`hw_sequencer.h`, where the implementation of the callbacks can be found in
|
||
|
the hardware sequencer folder. Almost at the end, you can see the block level
|
||
|
API (`dc/inc/hw`), which represents each DCN low-level block, such as HUBP,
|
||
|
DPP, MPC, OPTC, etc. Notice on the left side of the diagram that we have a
|
||
|
different set of layers representing the interaction with the DMUB
|
||
|
microcontroller.
|
||
|
|
||
|
Basic Objects
|
||
|
-------------
|
||
|
|
||
|
The below diagram outlines the basic display objects. In particular, pay
|
||
|
attention to the names in the boxes since they represent a data structure in
|
||
|
the driver:
|
||
|
|
||
|
.. kernel-figure:: dc-arch-overview.svg
|
||
|
|
||
|
Let's start with the central block in the image, `dc`. The `dc` struct is
|
||
|
initialized per GPU; for example, one GPU has one `dc` instance, two GPUs have
|
||
|
two `dc` instances, and so forth. In other words we have one 'dc' per 'amdgpu'
|
||
|
instance. In some ways, this object behaves like the `Singleton` pattern.
|
||
|
|
||
|
After the `dc` block in the diagram, you can see the `dc_link` component, which
|
||
|
is a low-level abstraction for the connector. One interesting aspect of the
|
||
|
image is that connectors are not part of the DCN block; they are defined by the
|
||
|
platform/board and not by the SoC. The `dc_link` struct is the high-level data
|
||
|
container with information such as connected sinks, connection status, signal
|
||
|
types, etc. After `dc_link`, there is the `dc_sink`, which is the object that
|
||
|
represents the connected display.
|
||
|
|
||
|
.. note::
|
||
|
For historical reasons, we used the name `dc_link`, which gives the
|
||
|
wrong impression that this abstraction only deals with physical connections
|
||
|
that the developer can easily manipulate. However, this also covers
|
||
|
conections like eDP or cases where the output is connected to other devices.
|
||
|
|
||
|
There are two structs that are not represented in the diagram since they were
|
||
|
elaborated in the DCN overview page (check the DCN block diagram :ref:`Display
|
||
|
Core Next (DCN) <dcn_overview>`); still, it is worth bringing back for this
|
||
|
overview which is `dc_stream` and `dc_state`. The `dc_stream` stores many
|
||
|
properties associated with the data transmission, but most importantly, it
|
||
|
represents the data flow from the connector to the display. Next we have
|
||
|
`dc_state`, which represents the logic state within the hardware at the moment;
|
||
|
`dc_state` is composed of `dc_stream` and `dc_plane`. The `dc_stream` is the DC
|
||
|
version of `drm_crtc` and represents the post-blending pipeline.
|
||
|
|
||
|
Speaking of the `dc_plane` data structure (first part of the diagram), you can
|
||
|
think about it as an abstraction similar to `drm_plane` that represents the
|
||
|
pre-blending portion of the pipeline. This image was probably processed by GFX
|
||
|
and is ready to be composited under a `dc_stream`. Normally, the driver may
|
||
|
have one or more `dc_plane` connected to the same `dc_stream`, which defines a
|
||
|
composition at the DC level.
|
||
|
|
||
|
Basic Operations
|
||
|
----------------
|
||
|
|
||
|
Now that we have covered the basic objects, it is time to examine some of the
|
||
|
basic hardware/software operations. Let's start with the `dc_create()`
|
||
|
function, which directly works with the `dc` data struct; this function behaves
|
||
|
like a constructor responsible for the basic software initialization and
|
||
|
preparing for enabling other parts of the API. It is important to highlight
|
||
|
that this operation does not touch any hardware configuration; it is only a
|
||
|
software initialization.
|
||
|
|
||
|
Next, we have the `dc_hardware_init()`, which also relies on the `dc` data
|
||
|
struct. Its main function is to put the hardware in a valid state. It is worth
|
||
|
highlighting that the hardware might initialize in an unknown state, and it is
|
||
|
a requirement to put it in a valid state; this function has multiple callbacks
|
||
|
for the hardware-specific initialization, whereas `dc_hardware_init` does the
|
||
|
hardware initialization and is the first point where we touch hardware.
|
||
|
|
||
|
The `dc_get_link_at_index` is an operation that depends on the `dc_link` data
|
||
|
structure. This function retrieves and enumerates all the `dc_links` available
|
||
|
on the device; this is required since this information is not part of the SoC
|
||
|
definition but depends on the board configuration. As soon as the `dc_link` is
|
||
|
initialized, it is useful to figure out if any of them are already connected to
|
||
|
the display by using the `dc_link_detect()` function. After the driver figures
|
||
|
out if any display is connected to the device, the challenging phase starts:
|
||
|
configuring the monitor to show something. Nonetheless, dealing with the ideal
|
||
|
configuration is not a DC task since this is the Display Manager (`amdgpu_dm`)
|
||
|
responsibility which in turn is responsible for dealing with the atomic
|
||
|
commits. The only interface DC provides to the configuration phase is the
|
||
|
function `dc_validate_with_context` that receives the configuration information
|
||
|
and, based on that, validates whether the hardware can support it or not. It is
|
||
|
important to add that even if the display supports some specific configuration,
|
||
|
it does not mean the DCN hardware can support it.
|
||
|
|
||
|
After the DM and DC agree upon the configuration, the stream configuration
|
||
|
phase starts. This task activates one or more `dc_stream` at this phase, and in
|
||
|
the best-case scenario, you might be able to turn the display on with a black
|
||
|
screen (it does not show anything yet since it does not have any plane
|
||
|
associated with it). The final step would be to call the
|
||
|
`dc_update_planes_and_stream,` which will add or remove planes.
|
||
|
|