| 1 | ====================
|
| 2 | DC Programming Model
|
| 3 | ====================
|
| 4 |
|
| 5 | In the :ref:`Display Core Next (DCN) <dcn_overview>` and :ref:`DCN Block
|
| 6 | <dcn_blocks>` pages, you learned about the hardware components and how they
|
| 7 | interact with each other. On this page, the focus is shifted to the display
|
| 8 | code architecture. Hence, it is reasonable to remind the reader that the code
|
| 9 | in DC is shared with other OSes; for this reason, DC provides a set of
|
| 10 | abstractions and operations to connect different APIs with the hardware
|
| 11 | configuration. See DC as a service available for a Display Manager (amdgpu_dm)
|
| 12 | to access and configure DCN/DCE hardware (DCE is also part of DC, but for
|
| 13 | simplicity's sake, this documentation only examines DCN).
|
| 14 |
|
| 15 | .. note::
|
| 16 | For this page, we will use the term GPU to refers to dGPU and APU.
|
| 17 |
|
| 18 | Overview
|
| 19 | ========
|
| 20 |
|
| 21 | From the display hardware perspective, it is plausible to expect that if a
|
| 22 | problem is well-defined, it will probably be implemented at the hardware level.
|
| 23 | On the other hand, when there are multiple ways of achieving something without
|
| 24 | a very well-defined scope, the solution is usually implemented as a policy at
|
| 25 | the DC level. In other words, some policies are defined in the DC core
|
| 26 | (resource management, power optimization, image quality, etc.), and the others
|
| 27 | implemented in hardware are enabled via DC configuration.
|
| 28 |
|
| 29 | In terms of hardware management, DCN has multiple instances of the same block
|
| 30 | (e.g., HUBP, DPP, MPC, etc), and during the driver execution, it might be
|
| 31 | necessary to use some of these instances. The core has policies in place for
|
| 32 | handling those instances. Regarding resource management, the DC objective is
|
| 33 | quite simple: minimize the hardware shuffle when the driver performs some
|
| 34 | actions. When the state changes from A to B, the transition is considered
|
| 35 | easier to maneuver if the hardware resource is still used for the same set of
|
| 36 | driver objects. Usually, adding and removing a resource to a `pipe_ctx` (more
|
| 37 | details below) is not a problem; however, moving a resource from one `pipe_ctx`
|
| 38 | to another should be avoided.
|
| 39 |
|
| 40 | Another area of influence for DC is power optimization, which has a myriad of
|
| 41 | arrangement possibilities. In some way, just displaying an image via DCN should
|
| 42 | be relatively straightforward; however, showing it with the best power
|
| 43 | footprint is more desirable, but it has many associated challenges.
|
| 44 | Unfortunately, there is no straight-forward analytic way to determine if a
|
| 45 | configuration is the best one for the context due to the enormous variety of
|
| 46 | variables related to this problem (e.g., many different DCN/DCE hardware
|
| 47 | versions, different displays configurations, etc.) for this reason DC
|
| 48 | implements a dedicated library for trying some configuration and verify if it
|
| 49 | is possible to support it or not. This type of policy is extremely complex to
|
| 50 | create and maintain, and amdgpu driver relies on Display Mode Library (DML) to
|
| 51 | generate the best decisions.
|
| 52 |
|
| 53 | In summary, DC must deal with the complexity of handling multiple scenarios and
|
| 54 | determine policies to manage them. All of the above information is conveyed to
|
| 55 | give the reader some idea about the complexity of driving a display from the
|
| 56 | driver's perspective. This page hopes to allow the reader to better navigate
|
| 57 | over the amdgpu display code.
|
| 58 |
|
| 59 | Display Driver Architecture Overview
|
| 60 | ====================================
|
| 61 |
|
| 62 | The diagram below provides an overview of the display driver architecture;
|
| 63 | notice it illustrates the software layers adopted by DC:
|
| 64 |
|
| 65 | .. kernel-figure:: dc-components.svg
|
| 66 |
|
| 67 | The first layer of the diagram is the high-level DC API represented by the
|
| 68 | `dc.h` file; below it are two big blocks represented by Core and Link. Next is
|
| 69 | the hardware configuration block; the main file describing it is
|
| 70 | the`hw_sequencer.h`, where the implementation of the callbacks can be found in
|
| 71 | the hardware sequencer folder. Almost at the end, you can see the block level
|
| 72 | API (`dc/inc/hw`), which represents each DCN low-level block, such as HUBP,
|
| 73 | DPP, MPC, OPTC, etc. Notice on the left side of the diagram that we have a
|
| 74 | different set of layers representing the interaction with the DMUB
|
| 75 | microcontroller.
|
| 76 |
|
| 77 | Basic Objects
|
| 78 | -------------
|
| 79 |
|
| 80 | The below diagram outlines the basic display objects. In particular, pay
|
| 81 | attention to the names in the boxes since they represent a data structure in
|
| 82 | the driver:
|
| 83 |
|
| 84 | .. kernel-figure:: dc-arch-overview.svg
|
| 85 |
|
| 86 | Let's start with the central block in the image, `dc`. The `dc` struct is
|
| 87 | initialized per GPU; for example, one GPU has one `dc` instance, two GPUs have
|
| 88 | two `dc` instances, and so forth. In other words we have one 'dc' per 'amdgpu'
|
| 89 | instance. In some ways, this object behaves like the `Singleton` pattern.
|
| 90 |
|
| 91 | After the `dc` block in the diagram, you can see the `dc_link` component, which
|
| 92 | is a low-level abstraction for the connector. One interesting aspect of the
|
| 93 | image is that connectors are not part of the DCN block; they are defined by the
|
| 94 | platform/board and not by the SoC. The `dc_link` struct is the high-level data
|
| 95 | container with information such as connected sinks, connection status, signal
|
| 96 | types, etc. After `dc_link`, there is the `dc_sink`, which is the object that
|
| 97 | represents the connected display.
|
| 98 |
|
| 99 | .. note::
|
| 100 | For historical reasons, we used the name `dc_link`, which gives the
|
| 101 | wrong impression that this abstraction only deals with physical connections
|
| 102 | that the developer can easily manipulate. However, this also covers
|
| 103 | connections like eDP or cases where the output is connected to other devices.
|
| 104 |
|
| 105 | There are two structs that are not represented in the diagram since they were
|
| 106 | elaborated in the DCN overview page (check the DCN block diagram :ref:`Display
|
| 107 | Core Next (DCN) <dcn_overview>`); still, it is worth bringing back for this
|
| 108 | overview which is `dc_stream` and `dc_state`. The `dc_stream` stores many
|
| 109 | properties associated with the data transmission, but most importantly, it
|
| 110 | represents the data flow from the connector to the display. Next we have
|
| 111 | `dc_state`, which represents the logic state within the hardware at the moment;
|
| 112 | `dc_state` is composed of `dc_stream` and `dc_plane`. The `dc_stream` is the DC
|
| 113 | version of `drm_crtc` and represents the post-blending pipeline.
|
| 114 |
|
| 115 | Speaking of the `dc_plane` data structure (first part of the diagram), you can
|
| 116 | think about it as an abstraction similar to `drm_plane` that represents the
|
| 117 | pre-blending portion of the pipeline. This image was probably processed by GFX
|
| 118 | and is ready to be composited under a `dc_stream`. Normally, the driver may
|
| 119 | have one or more `dc_plane` connected to the same `dc_stream`, which defines a
|
| 120 | composition at the DC level.
|
| 121 |
|
| 122 | Basic Operations
|
| 123 | ----------------
|
| 124 |
|
| 125 | Now that we have covered the basic objects, it is time to examine some of the
|
| 126 | basic hardware/software operations. Let's start with the `dc_create()`
|
| 127 | function, which directly works with the `dc` data struct; this function behaves
|
| 128 | like a constructor responsible for the basic software initialization and
|
| 129 | preparing for enabling other parts of the API. It is important to highlight
|
| 130 | that this operation does not touch any hardware configuration; it is only a
|
| 131 | software initialization.
|
| 132 |
|
| 133 | Next, we have the `dc_hardware_init()`, which also relies on the `dc` data
|
| 134 | struct. Its main function is to put the hardware in a valid state. It is worth
|
| 135 | highlighting that the hardware might initialize in an unknown state, and it is
|
| 136 | a requirement to put it in a valid state; this function has multiple callbacks
|
| 137 | for the hardware-specific initialization, whereas `dc_hardware_init` does the
|
| 138 | hardware initialization and is the first point where we touch hardware.
|
| 139 |
|
| 140 | The `dc_get_link_at_index` is an operation that depends on the `dc_link` data
|
| 141 | structure. This function retrieves and enumerates all the `dc_links` available
|
| 142 | on the device; this is required since this information is not part of the SoC
|
| 143 | definition but depends on the board configuration. As soon as the `dc_link` is
|
| 144 | initialized, it is useful to figure out if any of them are already connected to
|
| 145 | the display by using the `dc_link_detect()` function. After the driver figures
|
| 146 | out if any display is connected to the device, the challenging phase starts:
|
| 147 | configuring the monitor to show something. Nonetheless, dealing with the ideal
|
| 148 | configuration is not a DC task since this is the Display Manager (`amdgpu_dm`)
|
| 149 | responsibility which in turn is responsible for dealing with the atomic
|
| 150 | commits. The only interface DC provides to the configuration phase is the
|
| 151 | function `dc_validate_with_context` that receives the configuration information
|
| 152 | and, based on that, validates whether the hardware can support it or not. It is
|
| 153 | important to add that even if the display supports some specific configuration,
|
| 154 | it does not mean the DCN hardware can support it.
|
| 155 |
|
| 156 | After the DM and DC agree upon the configuration, the stream configuration
|
| 157 | phase starts. This task activates one or more `dc_stream` at this phase, and in
|
| 158 | the best-case scenario, you might be able to turn the display on with a black
|
| 159 | screen (it does not show anything yet since it does not have any plane
|
| 160 | associated with it). The final step would be to call the
|
| 161 | `dc_update_planes_and_stream,` which will add or remove planes.
|
| 162 |
|