| rjw | 1f88458 | 2022-01-06 17:20:42 +0800 | [diff] [blame] | 1 | ========================= | 
 | 2 | Kernel Mode Setting (KMS) | 
 | 3 | ========================= | 
 | 4 |  | 
 | 5 | Drivers must initialize the mode setting core by calling | 
 | 6 | :c:func:`drm_mode_config_init()` on the DRM device. The function | 
 | 7 | initializes the :c:type:`struct drm_device <drm_device>` | 
 | 8 | mode_config field and never fails. Once done, mode configuration must | 
 | 9 | be setup by initializing the following fields. | 
 | 10 |  | 
 | 11 | -  int min_width, min_height; int max_width, max_height; | 
 | 12 |    Minimum and maximum width and height of the frame buffers in pixel | 
 | 13 |    units. | 
 | 14 |  | 
 | 15 | -  struct drm_mode_config_funcs \*funcs; | 
 | 16 |    Mode setting functions. | 
 | 17 |  | 
 | 18 | Overview | 
 | 19 | ======== | 
 | 20 |  | 
 | 21 | .. kernel-render:: DOT | 
 | 22 |    :alt: KMS Display Pipeline | 
 | 23 |    :caption: KMS Display Pipeline Overview | 
 | 24 |  | 
 | 25 |    digraph "KMS" { | 
 | 26 |       node [shape=box] | 
 | 27 |  | 
 | 28 |       subgraph cluster_static { | 
 | 29 |           style=dashed | 
 | 30 |           label="Static Objects" | 
 | 31 |  | 
 | 32 |           node [bgcolor=grey style=filled] | 
 | 33 |           "drm_plane A" -> "drm_crtc" | 
 | 34 |           "drm_plane B" -> "drm_crtc" | 
 | 35 |           "drm_crtc" -> "drm_encoder A" | 
 | 36 |           "drm_crtc" -> "drm_encoder B" | 
 | 37 |       } | 
 | 38 |  | 
 | 39 |       subgraph cluster_user_created { | 
 | 40 |           style=dashed | 
 | 41 |           label="Userspace-Created" | 
 | 42 |  | 
 | 43 |           node [shape=oval] | 
 | 44 |           "drm_framebuffer 1" -> "drm_plane A" | 
 | 45 |           "drm_framebuffer 2" -> "drm_plane B" | 
 | 46 |       } | 
 | 47 |  | 
 | 48 |       subgraph cluster_connector { | 
 | 49 |           style=dashed | 
 | 50 |           label="Hotpluggable" | 
 | 51 |  | 
 | 52 |           "drm_encoder A" -> "drm_connector A" | 
 | 53 |           "drm_encoder B" -> "drm_connector B" | 
 | 54 |       } | 
 | 55 |    } | 
 | 56 |  | 
 | 57 | The basic object structure KMS presents to userspace is fairly simple. | 
 | 58 | Framebuffers (represented by :c:type:`struct drm_framebuffer <drm_framebuffer>`, | 
 | 59 | see `Frame Buffer Abstraction`_) feed into planes. One or more (or even no) | 
 | 60 | planes feed their pixel data into a CRTC (represented by :c:type:`struct | 
 | 61 | drm_crtc <drm_crtc>`, see `CRTC Abstraction`_) for blending. The precise | 
 | 62 | blending step is explained in more detail in `Plane Composition Properties`_ and | 
 | 63 | related chapters. | 
 | 64 |  | 
 | 65 | For the output routing the first step is encoders (represented by | 
 | 66 | :c:type:`struct drm_encoder <drm_encoder>`, see `Encoder Abstraction`_). Those | 
 | 67 | are really just internal artifacts of the helper libraries used to implement KMS | 
 | 68 | drivers. Besides that they make it unecessarily more complicated for userspace | 
 | 69 | to figure out which connections between a CRTC and a connector are possible, and | 
 | 70 | what kind of cloning is supported, they serve no purpose in the userspace API. | 
 | 71 | Unfortunately encoders have been exposed to userspace, hence can't remove them | 
 | 72 | at this point.  Futhermore the exposed restrictions are often wrongly set by | 
 | 73 | drivers, and in many cases not powerful enough to express the real restrictions. | 
 | 74 | A CRTC can be connected to multiple encoders, and for an active CRTC there must | 
 | 75 | be at least one encoder. | 
 | 76 |  | 
 | 77 | The final, and real, endpoint in the display chain is the connector (represented | 
 | 78 | by :c:type:`struct drm_connector <drm_connector>`, see `Connector | 
 | 79 | Abstraction`_). Connectors can have different possible encoders, but the kernel | 
 | 80 | driver selects which encoder to use for each connector. The use case is DVI, | 
 | 81 | which could switch between an analog and a digital encoder. Encoders can also | 
 | 82 | drive multiple different connectors. There is exactly one active connector for | 
 | 83 | every active encoder. | 
 | 84 |  | 
 | 85 | Internally the output pipeline is a bit more complex and matches today's | 
 | 86 | hardware more closely: | 
 | 87 |  | 
 | 88 | .. kernel-render:: DOT | 
 | 89 |    :alt: KMS Output Pipeline | 
 | 90 |    :caption: KMS Output Pipeline | 
 | 91 |  | 
 | 92 |    digraph "Output Pipeline" { | 
 | 93 |       node [shape=box] | 
 | 94 |  | 
 | 95 |       subgraph { | 
 | 96 |           "drm_crtc" [bgcolor=grey style=filled] | 
 | 97 |       } | 
 | 98 |  | 
 | 99 |       subgraph cluster_internal { | 
 | 100 |           style=dashed | 
 | 101 |           label="Internal Pipeline" | 
 | 102 |           { | 
 | 103 |               node [bgcolor=grey style=filled] | 
 | 104 |               "drm_encoder A"; | 
 | 105 |               "drm_encoder B"; | 
 | 106 |               "drm_encoder C"; | 
 | 107 |           } | 
 | 108 |  | 
 | 109 |           { | 
 | 110 |               node [bgcolor=grey style=filled] | 
 | 111 |               "drm_encoder B" -> "drm_bridge B" | 
 | 112 |               "drm_encoder C" -> "drm_bridge C1" | 
 | 113 |               "drm_bridge C1" -> "drm_bridge C2"; | 
 | 114 |           } | 
 | 115 |       } | 
 | 116 |  | 
 | 117 |       "drm_crtc" -> "drm_encoder A" | 
 | 118 |       "drm_crtc" -> "drm_encoder B" | 
 | 119 |       "drm_crtc" -> "drm_encoder C" | 
 | 120 |  | 
 | 121 |  | 
 | 122 |       subgraph cluster_output { | 
 | 123 |           style=dashed | 
 | 124 |           label="Outputs" | 
 | 125 |  | 
 | 126 |           "drm_encoder A" -> "drm_connector A"; | 
 | 127 |           "drm_bridge B" -> "drm_connector B"; | 
 | 128 |           "drm_bridge C2" -> "drm_connector C"; | 
 | 129 |  | 
 | 130 |           "drm_panel" | 
 | 131 |       } | 
 | 132 |    } | 
 | 133 |  | 
 | 134 | Internally two additional helper objects come into play. First, to be able to | 
 | 135 | share code for encoders (sometimes on the same SoC, sometimes off-chip) one or | 
 | 136 | more :ref:`drm_bridges` (represented by :c:type:`struct drm_bridge | 
 | 137 | <drm_bridge>`) can be linked to an encoder. This link is static and cannot be | 
 | 138 | changed, which means the cross-bar (if there is any) needs to be mapped between | 
 | 139 | the CRTC and any encoders. Often for drivers with bridges there's no code left | 
 | 140 | at the encoder level. Atomic drivers can leave out all the encoder callbacks to | 
 | 141 | essentially only leave a dummy routing object behind, which is needed for | 
 | 142 | backwards compatibility since encoders are exposed to userspace. | 
 | 143 |  | 
 | 144 | The second object is for panels, represented by :c:type:`struct drm_panel | 
 | 145 | <drm_panel>`, see :ref:`drm_panel_helper`. Panels do not have a fixed binding | 
 | 146 | point, but are generally linked to the driver private structure that embeds | 
 | 147 | :c:type:`struct drm_connector <drm_connector>`. | 
 | 148 |  | 
 | 149 | Note that currently the bridge chaining and interactions with connectors and | 
 | 150 | panels are still in-flux and not really fully sorted out yet. | 
 | 151 |  | 
 | 152 | KMS Core Structures and Functions | 
 | 153 | ================================= | 
 | 154 |  | 
 | 155 | .. kernel-doc:: include/drm/drm_mode_config.h | 
 | 156 |    :internal: | 
 | 157 |  | 
 | 158 | .. kernel-doc:: drivers/gpu/drm/drm_mode_config.c | 
 | 159 |    :export: | 
 | 160 |  | 
 | 161 | Modeset Base Object Abstraction | 
 | 162 | =============================== | 
 | 163 |  | 
 | 164 | .. kernel-render:: DOT | 
 | 165 |    :alt: Mode Objects and Properties | 
 | 166 |    :caption: Mode Objects and Properties | 
 | 167 |  | 
 | 168 |    digraph { | 
 | 169 |       node [shape=box] | 
 | 170 |  | 
 | 171 |       "drm_property A" -> "drm_mode_object A" | 
 | 172 |       "drm_property A" -> "drm_mode_object B" | 
 | 173 |       "drm_property B" -> "drm_mode_object A" | 
 | 174 |    } | 
 | 175 |  | 
 | 176 | The base structure for all KMS objects is :c:type:`struct drm_mode_object | 
 | 177 | <drm_mode_object>`. One of the base services it provides is tracking properties, | 
 | 178 | which are especially important for the atomic IOCTL (see `Atomic Mode | 
 | 179 | Setting`_). The somewhat surprising part here is that properties are not | 
 | 180 | directly instantiated on each object, but free-standing mode objects themselves, | 
 | 181 | represented by :c:type:`struct drm_property <drm_property>`, which only specify | 
 | 182 | the type and value range of a property. Any given property can be attached | 
 | 183 | multiple times to different objects using :c:func:`drm_object_attach_property() | 
 | 184 | <drm_object_attach_property>`. | 
 | 185 |  | 
 | 186 | .. kernel-doc:: include/drm/drm_mode_object.h | 
 | 187 |    :internal: | 
 | 188 |  | 
 | 189 | .. kernel-doc:: drivers/gpu/drm/drm_mode_object.c | 
 | 190 |    :export: | 
 | 191 |  | 
 | 192 | Atomic Mode Setting | 
 | 193 | =================== | 
 | 194 |  | 
 | 195 |  | 
 | 196 | .. kernel-render:: DOT | 
 | 197 |    :alt: Mode Objects and Properties | 
 | 198 |    :caption: Mode Objects and Properties | 
 | 199 |  | 
 | 200 |    digraph { | 
 | 201 |       node [shape=box] | 
 | 202 |  | 
 | 203 |       subgraph cluster_state { | 
 | 204 |           style=dashed | 
 | 205 |           label="Free-standing state" | 
 | 206 |  | 
 | 207 |           "drm_atomic_state" -> "duplicated drm_plane_state A" | 
 | 208 |           "drm_atomic_state" -> "duplicated drm_plane_state B" | 
 | 209 |           "drm_atomic_state" -> "duplicated drm_crtc_state" | 
 | 210 |           "drm_atomic_state" -> "duplicated drm_connector_state" | 
 | 211 |           "drm_atomic_state" -> "duplicated driver private state" | 
 | 212 |       } | 
 | 213 |  | 
 | 214 |       subgraph cluster_current { | 
 | 215 |           style=dashed | 
 | 216 |           label="Current state" | 
 | 217 |  | 
 | 218 |           "drm_device" -> "drm_plane A" | 
 | 219 |           "drm_device" -> "drm_plane B" | 
 | 220 |           "drm_device" -> "drm_crtc" | 
 | 221 |           "drm_device" -> "drm_connector" | 
 | 222 |           "drm_device" -> "driver private object" | 
 | 223 |  | 
 | 224 |           "drm_plane A" -> "drm_plane_state A" | 
 | 225 |           "drm_plane B" -> "drm_plane_state B" | 
 | 226 |           "drm_crtc" -> "drm_crtc_state" | 
 | 227 |           "drm_connector" -> "drm_connector_state" | 
 | 228 |           "driver private object" -> "driver private state" | 
 | 229 |       } | 
 | 230 |  | 
 | 231 |       "drm_atomic_state" -> "drm_device" [label="atomic_commit"] | 
 | 232 |       "duplicated drm_plane_state A" -> "drm_device"[style=invis] | 
 | 233 |    } | 
 | 234 |  | 
 | 235 | Atomic provides transactional modeset (including planes) updates, but a | 
 | 236 | bit differently from the usual transactional approach of try-commit and | 
 | 237 | rollback: | 
 | 238 |  | 
 | 239 | - Firstly, no hardware changes are allowed when the commit would fail. This | 
 | 240 |   allows us to implement the DRM_MODE_ATOMIC_TEST_ONLY mode, which allows | 
 | 241 |   userspace to explore whether certain configurations would work or not. | 
 | 242 |  | 
 | 243 | - This would still allow setting and rollback of just the software state, | 
 | 244 |   simplifying conversion of existing drivers. But auditing drivers for | 
 | 245 |   correctness of the atomic_check code becomes really hard with that: Rolling | 
 | 246 |   back changes in data structures all over the place is hard to get right. | 
 | 247 |  | 
 | 248 | - Lastly, for backwards compatibility and to support all use-cases, atomic | 
 | 249 |   updates need to be incremental and be able to execute in parallel. Hardware | 
 | 250 |   doesn't always allow it, but where possible plane updates on different CRTCs | 
 | 251 |   should not interfere, and not get stalled due to output routing changing on | 
 | 252 |   different CRTCs. | 
 | 253 |  | 
 | 254 | Taken all together there's two consequences for the atomic design: | 
 | 255 |  | 
 | 256 | - The overall state is split up into per-object state structures: | 
 | 257 |   :c:type:`struct drm_plane_state <drm_plane_state>` for planes, :c:type:`struct | 
 | 258 |   drm_crtc_state <drm_crtc_state>` for CRTCs and :c:type:`struct | 
 | 259 |   drm_connector_state <drm_connector_state>` for connectors. These are the only | 
 | 260 |   objects with userspace-visible and settable state. For internal state drivers | 
 | 261 |   can subclass these structures through embeddeding, or add entirely new state | 
 | 262 |   structures for their globally shared hardware functions. | 
 | 263 |  | 
 | 264 | - An atomic update is assembled and validated as an entirely free-standing pile | 
 | 265 |   of structures within the :c:type:`drm_atomic_state <drm_atomic_state>` | 
 | 266 |   container. Again drivers can subclass that container for their own state | 
 | 267 |   structure tracking needs. Only when a state is committed is it applied to the | 
 | 268 |   driver and modeset objects. This way rolling back an update boils down to | 
 | 269 |   releasing memory and unreferencing objects like framebuffers. | 
 | 270 |  | 
 | 271 | Read on in this chapter, and also in :ref:`drm_atomic_helper` for more detailed | 
 | 272 | coverage of specific topics. | 
 | 273 |  | 
 | 274 | Atomic Mode Setting Function Reference | 
 | 275 | -------------------------------------- | 
 | 276 |  | 
 | 277 | .. kernel-doc:: include/drm/drm_atomic.h | 
 | 278 |    :internal: | 
 | 279 |  | 
 | 280 | .. kernel-doc:: drivers/gpu/drm/drm_atomic.c | 
 | 281 |    :export: | 
 | 282 |  | 
 | 283 | CRTC Abstraction | 
 | 284 | ================ | 
 | 285 |  | 
 | 286 | .. kernel-doc:: drivers/gpu/drm/drm_crtc.c | 
 | 287 |    :doc: overview | 
 | 288 |  | 
 | 289 | CRTC Functions Reference | 
 | 290 | -------------------------------- | 
 | 291 |  | 
 | 292 | .. kernel-doc:: include/drm/drm_crtc.h | 
 | 293 |    :internal: | 
 | 294 |  | 
 | 295 | .. kernel-doc:: drivers/gpu/drm/drm_crtc.c | 
 | 296 |    :export: | 
 | 297 |  | 
 | 298 | Frame Buffer Abstraction | 
 | 299 | ======================== | 
 | 300 |  | 
 | 301 | .. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c | 
 | 302 |    :doc: overview | 
 | 303 |  | 
 | 304 | Frame Buffer Functions Reference | 
 | 305 | -------------------------------- | 
 | 306 |  | 
 | 307 | .. kernel-doc:: include/drm/drm_framebuffer.h | 
 | 308 |    :internal: | 
 | 309 |  | 
 | 310 | .. kernel-doc:: drivers/gpu/drm/drm_framebuffer.c | 
 | 311 |    :export: | 
 | 312 |  | 
 | 313 | DRM Format Handling | 
 | 314 | =================== | 
 | 315 |  | 
 | 316 | .. kernel-doc:: include/drm/drm_fourcc.h | 
 | 317 |    :internal: | 
 | 318 |  | 
 | 319 | .. kernel-doc:: drivers/gpu/drm/drm_fourcc.c | 
 | 320 |    :export: | 
 | 321 |  | 
 | 322 | Dumb Buffer Objects | 
 | 323 | =================== | 
 | 324 |  | 
 | 325 | .. kernel-doc:: drivers/gpu/drm/drm_dumb_buffers.c | 
 | 326 |    :doc: overview | 
 | 327 |  | 
 | 328 | Plane Abstraction | 
 | 329 | ================= | 
 | 330 |  | 
 | 331 | .. kernel-doc:: drivers/gpu/drm/drm_plane.c | 
 | 332 |    :doc: overview | 
 | 333 |  | 
 | 334 | Plane Functions Reference | 
 | 335 | ------------------------- | 
 | 336 |  | 
 | 337 | .. kernel-doc:: include/drm/drm_plane.h | 
 | 338 |    :internal: | 
 | 339 |  | 
 | 340 | .. kernel-doc:: drivers/gpu/drm/drm_plane.c | 
 | 341 |    :export: | 
 | 342 |  | 
 | 343 | Display Modes Function Reference | 
 | 344 | ================================ | 
 | 345 |  | 
 | 346 | .. kernel-doc:: include/drm/drm_modes.h | 
 | 347 |    :internal: | 
 | 348 |  | 
 | 349 | .. kernel-doc:: drivers/gpu/drm/drm_modes.c | 
 | 350 |    :export: | 
 | 351 |  | 
 | 352 | Connector Abstraction | 
 | 353 | ===================== | 
 | 354 |  | 
 | 355 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | 
 | 356 |    :doc: overview | 
 | 357 |  | 
 | 358 | Connector Functions Reference | 
 | 359 | ----------------------------- | 
 | 360 |  | 
 | 361 | .. kernel-doc:: include/drm/drm_connector.h | 
 | 362 |    :internal: | 
 | 363 |  | 
 | 364 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | 
 | 365 |    :export: | 
 | 366 |  | 
 | 367 | Encoder Abstraction | 
 | 368 | =================== | 
 | 369 |  | 
 | 370 | .. kernel-doc:: drivers/gpu/drm/drm_encoder.c | 
 | 371 |    :doc: overview | 
 | 372 |  | 
 | 373 | Encoder Functions Reference | 
 | 374 | --------------------------- | 
 | 375 |  | 
 | 376 | .. kernel-doc:: include/drm/drm_encoder.h | 
 | 377 |    :internal: | 
 | 378 |  | 
 | 379 | .. kernel-doc:: drivers/gpu/drm/drm_encoder.c | 
 | 380 |    :export: | 
 | 381 |  | 
 | 382 | KMS Initialization and Cleanup | 
 | 383 | ============================== | 
 | 384 |  | 
 | 385 | A KMS device is abstracted and exposed as a set of planes, CRTCs, | 
 | 386 | encoders and connectors. KMS drivers must thus create and initialize all | 
 | 387 | those objects at load time after initializing mode setting. | 
 | 388 |  | 
 | 389 | CRTCs (:c:type:`struct drm_crtc <drm_crtc>`) | 
 | 390 | -------------------------------------------- | 
 | 391 |  | 
 | 392 | A CRTC is an abstraction representing a part of the chip that contains a | 
 | 393 | pointer to a scanout buffer. Therefore, the number of CRTCs available | 
 | 394 | determines how many independent scanout buffers can be active at any | 
 | 395 | given time. The CRTC structure contains several fields to support this: | 
 | 396 | a pointer to some video memory (abstracted as a frame buffer object), a | 
 | 397 | display mode, and an (x, y) offset into the video memory to support | 
 | 398 | panning or configurations where one piece of video memory spans multiple | 
 | 399 | CRTCs. | 
 | 400 |  | 
 | 401 | CRTC Initialization | 
 | 402 | ~~~~~~~~~~~~~~~~~~~ | 
 | 403 |  | 
 | 404 | A KMS device must create and register at least one struct | 
 | 405 | :c:type:`struct drm_crtc <drm_crtc>` instance. The instance is | 
 | 406 | allocated and zeroed by the driver, possibly as part of a larger | 
 | 407 | structure, and registered with a call to :c:func:`drm_crtc_init()` | 
 | 408 | with a pointer to CRTC functions. | 
 | 409 |  | 
 | 410 |  | 
 | 411 | Cleanup | 
 | 412 | ------- | 
 | 413 |  | 
 | 414 | The DRM core manages its objects' lifetime. When an object is not needed | 
 | 415 | anymore the core calls its destroy function, which must clean up and | 
 | 416 | free every resource allocated for the object. Every | 
 | 417 | :c:func:`drm_\*_init()` call must be matched with a corresponding | 
 | 418 | :c:func:`drm_\*_cleanup()` call to cleanup CRTCs | 
 | 419 | (:c:func:`drm_crtc_cleanup()`), planes | 
 | 420 | (:c:func:`drm_plane_cleanup()`), encoders | 
 | 421 | (:c:func:`drm_encoder_cleanup()`) and connectors | 
 | 422 | (:c:func:`drm_connector_cleanup()`). Furthermore, connectors that | 
 | 423 | have been added to sysfs must be removed by a call to | 
 | 424 | :c:func:`drm_connector_unregister()` before calling | 
 | 425 | :c:func:`drm_connector_cleanup()`. | 
 | 426 |  | 
 | 427 | Connectors state change detection must be cleanup up with a call to | 
 | 428 | :c:func:`drm_kms_helper_poll_fini()`. | 
 | 429 |  | 
 | 430 | Output discovery and initialization example | 
 | 431 | ------------------------------------------- | 
 | 432 |  | 
 | 433 | .. code-block:: c | 
 | 434 |  | 
 | 435 |     void intel_crt_init(struct drm_device *dev) | 
 | 436 |     { | 
 | 437 |         struct drm_connector *connector; | 
 | 438 |         struct intel_output *intel_output; | 
 | 439 |  | 
 | 440 |         intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 
 | 441 |         if (!intel_output) | 
 | 442 |             return; | 
 | 443 |  | 
 | 444 |         connector = &intel_output->base; | 
 | 445 |         drm_connector_init(dev, &intel_output->base, | 
 | 446 |                    &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); | 
 | 447 |  | 
 | 448 |         drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs, | 
 | 449 |                  DRM_MODE_ENCODER_DAC); | 
 | 450 |  | 
 | 451 |         drm_mode_connector_attach_encoder(&intel_output->base, | 
 | 452 |                           &intel_output->enc); | 
 | 453 |  | 
 | 454 |         /* Set up the DDC bus. */ | 
 | 455 |         intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A"); | 
 | 456 |         if (!intel_output->ddc_bus) { | 
 | 457 |             dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | 
 | 458 |                    "failed.\n"); | 
 | 459 |             return; | 
 | 460 |         } | 
 | 461 |  | 
 | 462 |         intel_output->type = INTEL_OUTPUT_ANALOG; | 
 | 463 |         connector->interlace_allowed = 0; | 
 | 464 |         connector->doublescan_allowed = 0; | 
 | 465 |  | 
 | 466 |         drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs); | 
 | 467 |         drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 
 | 468 |  | 
 | 469 |         drm_connector_register(connector); | 
 | 470 |     } | 
 | 471 |  | 
 | 472 | In the example above (taken from the i915 driver), a CRTC, connector and | 
 | 473 | encoder combination is created. A device-specific i2c bus is also | 
 | 474 | created for fetching EDID data and performing monitor detection. Once | 
 | 475 | the process is complete, the new connector is registered with sysfs to | 
 | 476 | make its properties available to applications. | 
 | 477 |  | 
 | 478 | KMS Locking | 
 | 479 | =========== | 
 | 480 |  | 
 | 481 | .. kernel-doc:: drivers/gpu/drm/drm_modeset_lock.c | 
 | 482 |    :doc: kms locking | 
 | 483 |  | 
 | 484 | .. kernel-doc:: include/drm/drm_modeset_lock.h | 
 | 485 |    :internal: | 
 | 486 |  | 
 | 487 | .. kernel-doc:: drivers/gpu/drm/drm_modeset_lock.c | 
 | 488 |    :export: | 
 | 489 |  | 
 | 490 | KMS Properties | 
 | 491 | ============== | 
 | 492 |  | 
 | 493 | Property Types and Blob Property Support | 
 | 494 | ---------------------------------------- | 
 | 495 |  | 
 | 496 | .. kernel-doc:: drivers/gpu/drm/drm_property.c | 
 | 497 |    :doc: overview | 
 | 498 |  | 
 | 499 | .. kernel-doc:: include/drm/drm_property.h | 
 | 500 |    :internal: | 
 | 501 |  | 
 | 502 | .. kernel-doc:: drivers/gpu/drm/drm_property.c | 
 | 503 |    :export: | 
 | 504 |  | 
 | 505 | Standard Connector Properties | 
 | 506 | ----------------------------- | 
 | 507 |  | 
 | 508 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | 
 | 509 |    :doc: standard connector properties | 
 | 510 |  | 
 | 511 | Plane Composition Properties | 
 | 512 | ---------------------------- | 
 | 513 |  | 
 | 514 | .. kernel-doc:: drivers/gpu/drm/drm_blend.c | 
 | 515 |    :doc: overview | 
 | 516 |  | 
 | 517 | .. kernel-doc:: drivers/gpu/drm/drm_blend.c | 
 | 518 |    :export: | 
 | 519 |  | 
 | 520 | Color Management Properties | 
 | 521 | --------------------------- | 
 | 522 |  | 
 | 523 | .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c | 
 | 524 |    :doc: overview | 
 | 525 |  | 
 | 526 | .. kernel-doc:: drivers/gpu/drm/drm_color_mgmt.c | 
 | 527 |    :export: | 
 | 528 |  | 
 | 529 | Tile Group Property | 
 | 530 | ------------------- | 
 | 531 |  | 
 | 532 | .. kernel-doc:: drivers/gpu/drm/drm_connector.c | 
 | 533 |    :doc: Tile group | 
 | 534 |  | 
 | 535 | Explicit Fencing Properties | 
 | 536 | --------------------------- | 
 | 537 |  | 
 | 538 | .. kernel-doc:: drivers/gpu/drm/drm_atomic.c | 
 | 539 |    :doc: explicit fencing properties | 
 | 540 |  | 
 | 541 | Existing KMS Properties | 
 | 542 | ----------------------- | 
 | 543 |  | 
 | 544 | The following table gives description of drm properties exposed by | 
 | 545 | various modules/drivers. | 
 | 546 |  | 
 | 547 | .. csv-table:: | 
 | 548 |    :header-rows: 1 | 
 | 549 |    :file: kms-properties.csv | 
 | 550 |  | 
 | 551 | Vertical Blanking | 
 | 552 | ================= | 
 | 553 |  | 
 | 554 | .. kernel-doc:: drivers/gpu/drm/drm_vblank.c | 
 | 555 |    :doc: vblank handling | 
 | 556 |  | 
 | 557 | Vertical Blanking and Interrupt Handling Functions Reference | 
 | 558 | ------------------------------------------------------------ | 
 | 559 |  | 
 | 560 | .. kernel-doc:: include/drm/drm_vblank.h | 
 | 561 |    :internal: | 
 | 562 |  | 
 | 563 | .. kernel-doc:: drivers/gpu/drm/drm_vblank.c | 
 | 564 |    :export: |