1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun============================== 4*4882a593Smuzhiyun drm/komeda Arm display driver 5*4882a593Smuzhiyun============================== 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunThe drm/komeda driver supports the Arm display processor D71 and later products, 8*4882a593Smuzhiyunthis document gives a brief overview of driver design: how it works and why 9*4882a593Smuzhiyundesign it like that. 10*4882a593Smuzhiyun 11*4882a593SmuzhiyunOverview of D71 like display IPs 12*4882a593Smuzhiyun================================ 13*4882a593Smuzhiyun 14*4882a593SmuzhiyunFrom D71, Arm display IP begins to adopt a flexible and modularized 15*4882a593Smuzhiyunarchitecture. A display pipeline is made up of multiple individual and 16*4882a593Smuzhiyunfunctional pipeline stages called components, and every component has some 17*4882a593Smuzhiyunspecific capabilities that can give the flowed pipeline pixel data a 18*4882a593Smuzhiyunparticular processing. 19*4882a593Smuzhiyun 20*4882a593SmuzhiyunTypical D71 components: 21*4882a593Smuzhiyun 22*4882a593SmuzhiyunLayer 23*4882a593Smuzhiyun----- 24*4882a593SmuzhiyunLayer is the first pipeline stage, which prepares the pixel data for the next 25*4882a593Smuzhiyunstage. It fetches the pixel from memory, decodes it if it's AFBC, rotates the 26*4882a593Smuzhiyunsource image, unpacks or converts YUV pixels to the device internal RGB pixels, 27*4882a593Smuzhiyunthen adjusts the color_space of pixels if needed. 28*4882a593Smuzhiyun 29*4882a593SmuzhiyunScaler 30*4882a593Smuzhiyun------ 31*4882a593SmuzhiyunAs its name suggests, scaler takes responsibility for scaling, and D71 also 32*4882a593Smuzhiyunsupports image enhancements by scaler. 33*4882a593SmuzhiyunThe usage of scaler is very flexible and can be connected to layer output 34*4882a593Smuzhiyunfor layer scaling, or connected to compositor and scale the whole display 35*4882a593Smuzhiyunframe and then feed the output data into wb_layer which will then write it 36*4882a593Smuzhiyuninto memory. 37*4882a593Smuzhiyun 38*4882a593SmuzhiyunCompositor (compiz) 39*4882a593Smuzhiyun------------------- 40*4882a593SmuzhiyunCompositor blends multiple layers or pixel data flows into one single display 41*4882a593Smuzhiyunframe. its output frame can be fed into post image processor for showing it on 42*4882a593Smuzhiyunthe monitor or fed into wb_layer and written to memory at the same time. 43*4882a593Smuzhiyunuser can also insert a scaler between compositor and wb_layer to down scale 44*4882a593Smuzhiyunthe display frame first and then write to memory. 45*4882a593Smuzhiyun 46*4882a593SmuzhiyunWriteback Layer (wb_layer) 47*4882a593Smuzhiyun-------------------------- 48*4882a593SmuzhiyunWriteback layer does the opposite things of Layer, which connects to compiz 49*4882a593Smuzhiyunand writes the composition result to memory. 50*4882a593Smuzhiyun 51*4882a593SmuzhiyunPost image processor (improc) 52*4882a593Smuzhiyun----------------------------- 53*4882a593SmuzhiyunPost image processor adjusts frame data like gamma and color space to fit the 54*4882a593Smuzhiyunrequirements of the monitor. 55*4882a593Smuzhiyun 56*4882a593SmuzhiyunTiming controller (timing_ctrlr) 57*4882a593Smuzhiyun-------------------------------- 58*4882a593SmuzhiyunFinal stage of display pipeline, Timing controller is not for the pixel 59*4882a593Smuzhiyunhandling, but only for controlling the display timing. 60*4882a593Smuzhiyun 61*4882a593SmuzhiyunMerger 62*4882a593Smuzhiyun------ 63*4882a593SmuzhiyunD71 scaler mostly only has the half horizontal input/output capabilities 64*4882a593Smuzhiyuncompared with Layer, like if Layer supports 4K input size, the scaler only can 65*4882a593Smuzhiyunsupport 2K input/output in the same time. To achieve the ful frame scaling, D71 66*4882a593Smuzhiyunintroduces Layer Split, which splits the whole image to two half parts and feeds 67*4882a593Smuzhiyunthem to two Layers A and B, and does the scaling independently. After scaling 68*4882a593Smuzhiyunthe result need to be fed to merger to merge two part images together, and then 69*4882a593Smuzhiyunoutput merged result to compiz. 70*4882a593Smuzhiyun 71*4882a593SmuzhiyunSplitter 72*4882a593Smuzhiyun-------- 73*4882a593SmuzhiyunSimilar to Layer Split, but Splitter is used for writeback, which splits the 74*4882a593Smuzhiyuncompiz result to two parts and then feed them to two scalers. 75*4882a593Smuzhiyun 76*4882a593SmuzhiyunPossible D71 Pipeline usage 77*4882a593Smuzhiyun=========================== 78*4882a593Smuzhiyun 79*4882a593SmuzhiyunBenefitting from the modularized architecture, D71 pipelines can be easily 80*4882a593Smuzhiyunadjusted to fit different usages. And D71 has two pipelines, which support two 81*4882a593Smuzhiyuntypes of working mode: 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun- Dual display mode 84*4882a593Smuzhiyun Two pipelines work independently and separately to drive two display outputs. 85*4882a593Smuzhiyun 86*4882a593Smuzhiyun- Single display mode 87*4882a593Smuzhiyun Two pipelines work together to drive only one display output. 88*4882a593Smuzhiyun 89*4882a593Smuzhiyun On this mode, pipeline_B doesn't work indenpendently, but outputs its 90*4882a593Smuzhiyun composition result into pipeline_A, and its pixel timing also derived from 91*4882a593Smuzhiyun pipeline_A.timing_ctrlr. The pipeline_B works just like a "slave" of 92*4882a593Smuzhiyun pipeline_A(master) 93*4882a593Smuzhiyun 94*4882a593SmuzhiyunSingle pipeline data flow 95*4882a593Smuzhiyun------------------------- 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun.. kernel-render:: DOT 98*4882a593Smuzhiyun :alt: Single pipeline digraph 99*4882a593Smuzhiyun :caption: Single pipeline data flow 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun digraph single_ppl { 102*4882a593Smuzhiyun rankdir=LR; 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun subgraph { 105*4882a593Smuzhiyun "Memory"; 106*4882a593Smuzhiyun "Monitor"; 107*4882a593Smuzhiyun } 108*4882a593Smuzhiyun 109*4882a593Smuzhiyun subgraph cluster_pipeline { 110*4882a593Smuzhiyun style=dashed 111*4882a593Smuzhiyun node [shape=box] 112*4882a593Smuzhiyun { 113*4882a593Smuzhiyun node [bgcolor=grey style=dashed] 114*4882a593Smuzhiyun "Scaler-0"; 115*4882a593Smuzhiyun "Scaler-1"; 116*4882a593Smuzhiyun "Scaler-0/1" 117*4882a593Smuzhiyun } 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun node [bgcolor=grey style=filled] 120*4882a593Smuzhiyun "Layer-0" -> "Scaler-0" 121*4882a593Smuzhiyun "Layer-1" -> "Scaler-0" 122*4882a593Smuzhiyun "Layer-2" -> "Scaler-1" 123*4882a593Smuzhiyun "Layer-3" -> "Scaler-1" 124*4882a593Smuzhiyun 125*4882a593Smuzhiyun "Layer-0" -> "Compiz" 126*4882a593Smuzhiyun "Layer-1" -> "Compiz" 127*4882a593Smuzhiyun "Layer-2" -> "Compiz" 128*4882a593Smuzhiyun "Layer-3" -> "Compiz" 129*4882a593Smuzhiyun "Scaler-0" -> "Compiz" 130*4882a593Smuzhiyun "Scaler-1" -> "Compiz" 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun "Compiz" -> "Scaler-0/1" -> "Wb_layer" 133*4882a593Smuzhiyun "Compiz" -> "Improc" -> "Timing Controller" 134*4882a593Smuzhiyun } 135*4882a593Smuzhiyun 136*4882a593Smuzhiyun "Wb_layer" -> "Memory" 137*4882a593Smuzhiyun "Timing Controller" -> "Monitor" 138*4882a593Smuzhiyun } 139*4882a593Smuzhiyun 140*4882a593SmuzhiyunDual pipeline with Slave enabled 141*4882a593Smuzhiyun-------------------------------- 142*4882a593Smuzhiyun 143*4882a593Smuzhiyun.. kernel-render:: DOT 144*4882a593Smuzhiyun :alt: Slave pipeline digraph 145*4882a593Smuzhiyun :caption: Slave pipeline enabled data flow 146*4882a593Smuzhiyun 147*4882a593Smuzhiyun digraph slave_ppl { 148*4882a593Smuzhiyun rankdir=LR; 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun subgraph { 151*4882a593Smuzhiyun "Memory"; 152*4882a593Smuzhiyun "Monitor"; 153*4882a593Smuzhiyun } 154*4882a593Smuzhiyun node [shape=box] 155*4882a593Smuzhiyun subgraph cluster_pipeline_slave { 156*4882a593Smuzhiyun style=dashed 157*4882a593Smuzhiyun label="Slave Pipeline_B" 158*4882a593Smuzhiyun node [shape=box] 159*4882a593Smuzhiyun { 160*4882a593Smuzhiyun node [bgcolor=grey style=dashed] 161*4882a593Smuzhiyun "Slave.Scaler-0"; 162*4882a593Smuzhiyun "Slave.Scaler-1"; 163*4882a593Smuzhiyun } 164*4882a593Smuzhiyun 165*4882a593Smuzhiyun node [bgcolor=grey style=filled] 166*4882a593Smuzhiyun "Slave.Layer-0" -> "Slave.Scaler-0" 167*4882a593Smuzhiyun "Slave.Layer-1" -> "Slave.Scaler-0" 168*4882a593Smuzhiyun "Slave.Layer-2" -> "Slave.Scaler-1" 169*4882a593Smuzhiyun "Slave.Layer-3" -> "Slave.Scaler-1" 170*4882a593Smuzhiyun 171*4882a593Smuzhiyun "Slave.Layer-0" -> "Slave.Compiz" 172*4882a593Smuzhiyun "Slave.Layer-1" -> "Slave.Compiz" 173*4882a593Smuzhiyun "Slave.Layer-2" -> "Slave.Compiz" 174*4882a593Smuzhiyun "Slave.Layer-3" -> "Slave.Compiz" 175*4882a593Smuzhiyun "Slave.Scaler-0" -> "Slave.Compiz" 176*4882a593Smuzhiyun "Slave.Scaler-1" -> "Slave.Compiz" 177*4882a593Smuzhiyun } 178*4882a593Smuzhiyun 179*4882a593Smuzhiyun subgraph cluster_pipeline_master { 180*4882a593Smuzhiyun style=dashed 181*4882a593Smuzhiyun label="Master Pipeline_A" 182*4882a593Smuzhiyun node [shape=box] 183*4882a593Smuzhiyun { 184*4882a593Smuzhiyun node [bgcolor=grey style=dashed] 185*4882a593Smuzhiyun "Scaler-0"; 186*4882a593Smuzhiyun "Scaler-1"; 187*4882a593Smuzhiyun "Scaler-0/1" 188*4882a593Smuzhiyun } 189*4882a593Smuzhiyun 190*4882a593Smuzhiyun node [bgcolor=grey style=filled] 191*4882a593Smuzhiyun "Layer-0" -> "Scaler-0" 192*4882a593Smuzhiyun "Layer-1" -> "Scaler-0" 193*4882a593Smuzhiyun "Layer-2" -> "Scaler-1" 194*4882a593Smuzhiyun "Layer-3" -> "Scaler-1" 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun "Slave.Compiz" -> "Compiz" 197*4882a593Smuzhiyun "Layer-0" -> "Compiz" 198*4882a593Smuzhiyun "Layer-1" -> "Compiz" 199*4882a593Smuzhiyun "Layer-2" -> "Compiz" 200*4882a593Smuzhiyun "Layer-3" -> "Compiz" 201*4882a593Smuzhiyun "Scaler-0" -> "Compiz" 202*4882a593Smuzhiyun "Scaler-1" -> "Compiz" 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun "Compiz" -> "Scaler-0/1" -> "Wb_layer" 205*4882a593Smuzhiyun "Compiz" -> "Improc" -> "Timing Controller" 206*4882a593Smuzhiyun } 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun "Wb_layer" -> "Memory" 209*4882a593Smuzhiyun "Timing Controller" -> "Monitor" 210*4882a593Smuzhiyun } 211*4882a593Smuzhiyun 212*4882a593SmuzhiyunSub-pipelines for input and output 213*4882a593Smuzhiyun---------------------------------- 214*4882a593Smuzhiyun 215*4882a593SmuzhiyunA complete display pipeline can be easily divided into three sub-pipelines 216*4882a593Smuzhiyunaccording to the in/out usage. 217*4882a593Smuzhiyun 218*4882a593SmuzhiyunLayer(input) pipeline 219*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~ 220*4882a593Smuzhiyun 221*4882a593Smuzhiyun.. kernel-render:: DOT 222*4882a593Smuzhiyun :alt: Layer data digraph 223*4882a593Smuzhiyun :caption: Layer (input) data flow 224*4882a593Smuzhiyun 225*4882a593Smuzhiyun digraph layer_data_flow { 226*4882a593Smuzhiyun rankdir=LR; 227*4882a593Smuzhiyun node [shape=box] 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun { 230*4882a593Smuzhiyun node [bgcolor=grey style=dashed] 231*4882a593Smuzhiyun "Scaler-n"; 232*4882a593Smuzhiyun } 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun "Layer-n" -> "Scaler-n" -> "Compiz" 235*4882a593Smuzhiyun } 236*4882a593Smuzhiyun 237*4882a593Smuzhiyun.. kernel-render:: DOT 238*4882a593Smuzhiyun :alt: Layer Split digraph 239*4882a593Smuzhiyun :caption: Layer Split pipeline 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun digraph layer_data_flow { 242*4882a593Smuzhiyun rankdir=LR; 243*4882a593Smuzhiyun node [shape=box] 244*4882a593Smuzhiyun 245*4882a593Smuzhiyun "Layer-0/1" -> "Scaler-0" -> "Merger" 246*4882a593Smuzhiyun "Layer-2/3" -> "Scaler-1" -> "Merger" 247*4882a593Smuzhiyun "Merger" -> "Compiz" 248*4882a593Smuzhiyun } 249*4882a593Smuzhiyun 250*4882a593SmuzhiyunWriteback(output) pipeline 251*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~~~~ 252*4882a593Smuzhiyun.. kernel-render:: DOT 253*4882a593Smuzhiyun :alt: writeback digraph 254*4882a593Smuzhiyun :caption: Writeback(output) data flow 255*4882a593Smuzhiyun 256*4882a593Smuzhiyun digraph writeback_data_flow { 257*4882a593Smuzhiyun rankdir=LR; 258*4882a593Smuzhiyun node [shape=box] 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun { 261*4882a593Smuzhiyun node [bgcolor=grey style=dashed] 262*4882a593Smuzhiyun "Scaler-n"; 263*4882a593Smuzhiyun } 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun "Compiz" -> "Scaler-n" -> "Wb_layer" 266*4882a593Smuzhiyun } 267*4882a593Smuzhiyun 268*4882a593Smuzhiyun.. kernel-render:: DOT 269*4882a593Smuzhiyun :alt: split writeback digraph 270*4882a593Smuzhiyun :caption: Writeback(output) Split data flow 271*4882a593Smuzhiyun 272*4882a593Smuzhiyun digraph writeback_data_flow { 273*4882a593Smuzhiyun rankdir=LR; 274*4882a593Smuzhiyun node [shape=box] 275*4882a593Smuzhiyun 276*4882a593Smuzhiyun "Compiz" -> "Splitter" 277*4882a593Smuzhiyun "Splitter" -> "Scaler-0" -> "Merger" 278*4882a593Smuzhiyun "Splitter" -> "Scaler-1" -> "Merger" 279*4882a593Smuzhiyun "Merger" -> "Wb_layer" 280*4882a593Smuzhiyun } 281*4882a593Smuzhiyun 282*4882a593SmuzhiyunDisplay output pipeline 283*4882a593Smuzhiyun~~~~~~~~~~~~~~~~~~~~~~~ 284*4882a593Smuzhiyun.. kernel-render:: DOT 285*4882a593Smuzhiyun :alt: display digraph 286*4882a593Smuzhiyun :caption: display output data flow 287*4882a593Smuzhiyun 288*4882a593Smuzhiyun digraph single_ppl { 289*4882a593Smuzhiyun rankdir=LR; 290*4882a593Smuzhiyun node [shape=box] 291*4882a593Smuzhiyun 292*4882a593Smuzhiyun "Compiz" -> "Improc" -> "Timing Controller" 293*4882a593Smuzhiyun } 294*4882a593Smuzhiyun 295*4882a593SmuzhiyunIn the following section we'll see these three sub-pipelines will be handled 296*4882a593Smuzhiyunby KMS-plane/wb_conn/crtc respectively. 297*4882a593Smuzhiyun 298*4882a593SmuzhiyunKomeda Resource abstraction 299*4882a593Smuzhiyun=========================== 300*4882a593Smuzhiyun 301*4882a593Smuzhiyunstruct komeda_pipeline/component 302*4882a593Smuzhiyun-------------------------------- 303*4882a593Smuzhiyun 304*4882a593SmuzhiyunTo fully utilize and easily access/configure the HW, the driver side also uses 305*4882a593Smuzhiyuna similar architecture: Pipeline/Component to describe the HW features and 306*4882a593Smuzhiyuncapabilities, and a specific component includes two parts: 307*4882a593Smuzhiyun 308*4882a593Smuzhiyun- Data flow controlling. 309*4882a593Smuzhiyun- Specific component capabilities and features. 310*4882a593Smuzhiyun 311*4882a593SmuzhiyunSo the driver defines a common header struct komeda_component to describe the 312*4882a593Smuzhiyundata flow control and all specific components are a subclass of this base 313*4882a593Smuzhiyunstructure. 314*4882a593Smuzhiyun 315*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h 316*4882a593Smuzhiyun :internal: 317*4882a593Smuzhiyun 318*4882a593SmuzhiyunResource discovery and initialization 319*4882a593Smuzhiyun===================================== 320*4882a593Smuzhiyun 321*4882a593SmuzhiyunPipeline and component are used to describe how to handle the pixel data. We 322*4882a593Smuzhiyunstill need a @struct komeda_dev to describe the whole view of the device, and 323*4882a593Smuzhiyunthe control-abilites of device. 324*4882a593Smuzhiyun 325*4882a593SmuzhiyunWe have &komeda_dev, &komeda_pipeline, &komeda_component. Now fill devices with 326*4882a593Smuzhiyunpipelines. Since komeda is not for D71 only but also intended for later products, 327*4882a593Smuzhiyunof course we’d better share as much as possible between different products. To 328*4882a593Smuzhiyunachieve this, split the komeda device into two layers: CORE and CHIP. 329*4882a593Smuzhiyun 330*4882a593Smuzhiyun- CORE: for common features and capabilities handling. 331*4882a593Smuzhiyun- CHIP: for register programing and HW specific feature (limitation) handling. 332*4882a593Smuzhiyun 333*4882a593SmuzhiyunCORE can access CHIP by three chip function structures: 334*4882a593Smuzhiyun 335*4882a593Smuzhiyun- struct komeda_dev_funcs 336*4882a593Smuzhiyun- struct komeda_pipeline_funcs 337*4882a593Smuzhiyun- struct komeda_component_funcs 338*4882a593Smuzhiyun 339*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_dev.h 340*4882a593Smuzhiyun :internal: 341*4882a593Smuzhiyun 342*4882a593SmuzhiyunFormat handling 343*4882a593Smuzhiyun=============== 344*4882a593Smuzhiyun 345*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_format_caps.h 346*4882a593Smuzhiyun :internal: 347*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_framebuffer.h 348*4882a593Smuzhiyun :internal: 349*4882a593Smuzhiyun 350*4882a593SmuzhiyunAttach komeda_dev to DRM-KMS 351*4882a593Smuzhiyun============================ 352*4882a593Smuzhiyun 353*4882a593SmuzhiyunKomeda abstracts resources by pipeline/component, but DRM-KMS uses 354*4882a593Smuzhiyuncrtc/plane/connector. One KMS-obj cannot represent only one single component, 355*4882a593Smuzhiyunsince the requirements of a single KMS object cannot simply be achieved by a 356*4882a593Smuzhiyunsingle component, usually that needs multiple components to fit the requirement. 357*4882a593SmuzhiyunLike set mode, gamma, ctm for KMS all target on CRTC-obj, but komeda needs 358*4882a593Smuzhiyuncompiz, improc and timing_ctrlr to work together to fit these requirements. 359*4882a593SmuzhiyunAnd a KMS-Plane may require multiple komeda resources: layer/scaler/compiz. 360*4882a593Smuzhiyun 361*4882a593SmuzhiyunSo, one KMS-Obj represents a sub-pipeline of komeda resources. 362*4882a593Smuzhiyun 363*4882a593Smuzhiyun- Plane: `Layer(input) pipeline`_ 364*4882a593Smuzhiyun- Wb_connector: `Writeback(output) pipeline`_ 365*4882a593Smuzhiyun- Crtc: `Display output pipeline`_ 366*4882a593Smuzhiyun 367*4882a593SmuzhiyunSo, for komeda, we treat KMS crtc/plane/connector as users of pipeline and 368*4882a593Smuzhiyuncomponent, and at any one time a pipeline/component only can be used by one 369*4882a593Smuzhiyunuser. And pipeline/component will be treated as private object of DRM-KMS; the 370*4882a593Smuzhiyunstate will be managed by drm_atomic_state as well. 371*4882a593Smuzhiyun 372*4882a593SmuzhiyunHow to map plane to Layer(input) pipeline 373*4882a593Smuzhiyun----------------------------------------- 374*4882a593Smuzhiyun 375*4882a593SmuzhiyunKomeda has multiple Layer input pipelines, see: 376*4882a593Smuzhiyun- `Single pipeline data flow`_ 377*4882a593Smuzhiyun- `Dual pipeline with Slave enabled`_ 378*4882a593Smuzhiyun 379*4882a593SmuzhiyunThe easiest way is binding a plane to a fixed Layer pipeline, but consider the 380*4882a593Smuzhiyunkomeda capabilities: 381*4882a593Smuzhiyun 382*4882a593Smuzhiyun- Layer Split, See `Layer(input) pipeline`_ 383*4882a593Smuzhiyun 384*4882a593Smuzhiyun Layer_Split is quite complicated feature, which splits a big image into two 385*4882a593Smuzhiyun parts and handles it by two layers and two scalers individually. But it 386*4882a593Smuzhiyun imports an edge problem or effect in the middle of the image after the split. 387*4882a593Smuzhiyun To avoid such a problem, it needs a complicated Split calculation and some 388*4882a593Smuzhiyun special configurations to the layer and scaler. We'd better hide such HW 389*4882a593Smuzhiyun related complexity to user mode. 390*4882a593Smuzhiyun 391*4882a593Smuzhiyun- Slave pipeline, See `Dual pipeline with Slave enabled`_ 392*4882a593Smuzhiyun 393*4882a593Smuzhiyun Since the compiz component doesn't output alpha value, the slave pipeline 394*4882a593Smuzhiyun only can be used for bottom layers composition. The komeda driver wants to 395*4882a593Smuzhiyun hide this limitation to the user. The way to do this is to pick a suitable 396*4882a593Smuzhiyun Layer according to plane_state->zpos. 397*4882a593Smuzhiyun 398*4882a593SmuzhiyunSo for komeda, the KMS-plane doesn't represent a fixed komeda layer pipeline, 399*4882a593Smuzhiyunbut multiple Layers with same capabilities. Komeda will select one or more 400*4882a593SmuzhiyunLayers to fit the requirement of one KMS-plane. 401*4882a593Smuzhiyun 402*4882a593SmuzhiyunMake component/pipeline to be drm_private_obj 403*4882a593Smuzhiyun--------------------------------------------- 404*4882a593Smuzhiyun 405*4882a593SmuzhiyunAdd :c:type:`drm_private_obj` to :c:type:`komeda_component`, :c:type:`komeda_pipeline` 406*4882a593Smuzhiyun 407*4882a593Smuzhiyun.. code-block:: c 408*4882a593Smuzhiyun 409*4882a593Smuzhiyun struct komeda_component { 410*4882a593Smuzhiyun struct drm_private_obj obj; 411*4882a593Smuzhiyun ... 412*4882a593Smuzhiyun } 413*4882a593Smuzhiyun 414*4882a593Smuzhiyun struct komeda_pipeline { 415*4882a593Smuzhiyun struct drm_private_obj obj; 416*4882a593Smuzhiyun ... 417*4882a593Smuzhiyun } 418*4882a593Smuzhiyun 419*4882a593SmuzhiyunTracking component_state/pipeline_state by drm_atomic_state 420*4882a593Smuzhiyun----------------------------------------------------------- 421*4882a593Smuzhiyun 422*4882a593SmuzhiyunAdd :c:type:`drm_private_state` and user to :c:type:`komeda_component_state`, 423*4882a593Smuzhiyun:c:type:`komeda_pipeline_state` 424*4882a593Smuzhiyun 425*4882a593Smuzhiyun.. code-block:: c 426*4882a593Smuzhiyun 427*4882a593Smuzhiyun struct komeda_component_state { 428*4882a593Smuzhiyun struct drm_private_state obj; 429*4882a593Smuzhiyun void *binding_user; 430*4882a593Smuzhiyun ... 431*4882a593Smuzhiyun } 432*4882a593Smuzhiyun 433*4882a593Smuzhiyun struct komeda_pipeline_state { 434*4882a593Smuzhiyun struct drm_private_state obj; 435*4882a593Smuzhiyun struct drm_crtc *crtc; 436*4882a593Smuzhiyun ... 437*4882a593Smuzhiyun } 438*4882a593Smuzhiyun 439*4882a593Smuzhiyunkomeda component validation 440*4882a593Smuzhiyun--------------------------- 441*4882a593Smuzhiyun 442*4882a593SmuzhiyunKomeda has multiple types of components, but the process of validation are 443*4882a593Smuzhiyunsimilar, usually including the following steps: 444*4882a593Smuzhiyun 445*4882a593Smuzhiyun.. code-block:: c 446*4882a593Smuzhiyun 447*4882a593Smuzhiyun int komeda_xxxx_validate(struct komeda_component_xxx xxx_comp, 448*4882a593Smuzhiyun struct komeda_component_output *input_dflow, 449*4882a593Smuzhiyun struct drm_plane/crtc/connector *user, 450*4882a593Smuzhiyun struct drm_plane/crtc/connector_state, *user_state) 451*4882a593Smuzhiyun { 452*4882a593Smuzhiyun setup 1: check if component is needed, like the scaler is optional depending 453*4882a593Smuzhiyun on the user_state; if unneeded, just return, and the caller will 454*4882a593Smuzhiyun put the data flow into next stage. 455*4882a593Smuzhiyun Setup 2: check user_state with component features and capabilities to see 456*4882a593Smuzhiyun if requirements can be met; if not, return fail. 457*4882a593Smuzhiyun Setup 3: get component_state from drm_atomic_state, and try set to set 458*4882a593Smuzhiyun user to component; fail if component has been assigned to another 459*4882a593Smuzhiyun user already. 460*4882a593Smuzhiyun Setup 3: configure the component_state, like set its input component, 461*4882a593Smuzhiyun convert user_state to component specific state. 462*4882a593Smuzhiyun Setup 4: adjust the input_dflow and prepare it for the next stage. 463*4882a593Smuzhiyun } 464*4882a593Smuzhiyun 465*4882a593Smuzhiyunkomeda_kms Abstraction 466*4882a593Smuzhiyun---------------------- 467*4882a593Smuzhiyun 468*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_kms.h 469*4882a593Smuzhiyun :internal: 470*4882a593Smuzhiyun 471*4882a593Smuzhiyunkomde_kms Functions 472*4882a593Smuzhiyun------------------- 473*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_crtc.c 474*4882a593Smuzhiyun :internal: 475*4882a593Smuzhiyun.. kernel-doc:: drivers/gpu/drm/arm/display/komeda/komeda_plane.c 476*4882a593Smuzhiyun :internal: 477*4882a593Smuzhiyun 478*4882a593SmuzhiyunBuild komeda to be a Linux module driver 479*4882a593Smuzhiyun======================================== 480*4882a593Smuzhiyun 481*4882a593SmuzhiyunNow we have two level devices: 482*4882a593Smuzhiyun 483*4882a593Smuzhiyun- komeda_dev: describes the real display hardware. 484*4882a593Smuzhiyun- komeda_kms_dev: attachs or connects komeda_dev to DRM-KMS. 485*4882a593Smuzhiyun 486*4882a593SmuzhiyunAll komeda operations are supplied or operated by komeda_dev or komeda_kms_dev, 487*4882a593Smuzhiyunthe module driver is only a simple wrapper to pass the Linux command 488*4882a593Smuzhiyun(probe/remove/pm) into komeda_dev or komeda_kms_dev. 489