drm/komeda Arm display driver¶
The drm/komeda driver supports the Arm display processor D71 and later products,this document gives a brief overview of driver design: how it works and whydesign it like that.
Overview of D71 like display IPs¶
From D71, Arm display IP begins to adopt a flexible and modularizedarchitecture. A display pipeline is made up of multiple individual andfunctional pipeline stages called components, and every component has somespecific capabilities that can give the flowed pipeline pixel data aparticular processing.
Typical D71 components:
Layer¶
Layer is the first pipeline stage, which prepares the pixel data for the nextstage. It fetches the pixel from memory, decodes it if it’s AFBC, rotates thesource image, unpacks or converts YUV pixels to the device internal RGB pixels,then adjusts the color_space of pixels if needed.
Scaler¶
As its name suggests, scaler takes responsibility for scaling, and D71 alsosupports image enhancements by scaler.The usage of scaler is very flexible and can be connected to layer outputfor layer scaling, or connected to compositor and scale the whole displayframe and then feed the output data into wb_layer which will then write itinto memory.
Compositor (compiz)¶
Compositor blends multiple layers or pixel data flows into one single displayframe. its output frame can be fed into post image processor for showing it onthe monitor or fed into wb_layer and written to memory at the same time.user can also insert a scaler between compositor and wb_layer to down scalethe display frame first and then write to memory.
Writeback Layer (wb_layer)¶
Writeback layer does the opposite things of Layer, which connects to compizand writes the composition result to memory.
Post image processor (improc)¶
Post image processor adjusts frame data like gamma and color space to fit therequirements of the monitor.
Timing controller (timing_ctrlr)¶
Final stage of display pipeline, Timing controller is not for the pixelhandling, but only for controlling the display timing.
Merger¶
D71 scaler mostly only has the half horizontal input/output capabilitiescompared with Layer, like if Layer supports 4K input size, the scaler only cansupport 2K input/output in the same time. To achieve the ful frame scaling, D71introduces Layer Split, which splits the whole image to two half parts and feedsthem to two Layers A and B, and does the scaling independently. After scalingthe result need to be fed to merger to merge two part images together, and thenoutput merged result to compiz.
Splitter¶
Similar to Layer Split, but Splitter is used for writeback, which splits thecompiz result to two parts and then feed them to two scalers.
Possible D71 Pipeline usage¶
Benefitting from the modularized architecture, D71 pipelines can be easilyadjusted to fit different usages. And D71 has two pipelines, which support twotypes of working mode:
Dual display modeTwo pipelines work independently and separately to drive two display outputs.
Single display modeTwo pipelines work together to drive only one display output.
On this mode, pipeline_B doesn’t work independently, but outputs itscomposition result into pipeline_A, and its pixel timing also derived frompipeline_A.timing_ctrlr. The pipeline_B works just like a “slave” ofpipeline_A(master)
Single pipeline data flow¶
digraph single_ppl { rankdir=LR; subgraph { "Memory"; "Monitor"; } subgraph cluster_pipeline { style=dashed node [shape=box] { node [bgcolor=grey style=dashed] "Scaler-0"; "Scaler-1"; "Scaler-0/1" } node [bgcolor=grey style=filled] "Layer-0" -> "Scaler-0" "Layer-1" -> "Scaler-0" "Layer-2" -> "Scaler-1" "Layer-3" -> "Scaler-1" "Layer-0" -> "Compiz" "Layer-1" -> "Compiz" "Layer-2" -> "Compiz" "Layer-3" -> "Compiz" "Scaler-0" -> "Compiz" "Scaler-1" -> "Compiz" "Compiz" -> "Scaler-0/1" -> "Wb_layer" "Compiz" -> "Improc" -> "Timing Controller" } "Wb_layer" -> "Memory" "Timing Controller" -> "Monitor"}Single pipeline data flow¶
Dual pipeline with Slave enabled¶
digraph slave_ppl { rankdir=LR; subgraph { "Memory"; "Monitor"; } node [shape=box] subgraph cluster_pipeline_slave { style=dashed label="Slave Pipeline_B" node [shape=box] { node [bgcolor=grey style=dashed] "Slave.Scaler-0"; "Slave.Scaler-1"; } node [bgcolor=grey style=filled] "Slave.Layer-0" -> "Slave.Scaler-0" "Slave.Layer-1" -> "Slave.Scaler-0" "Slave.Layer-2" -> "Slave.Scaler-1" "Slave.Layer-3" -> "Slave.Scaler-1" "Slave.Layer-0" -> "Slave.Compiz" "Slave.Layer-1" -> "Slave.Compiz" "Slave.Layer-2" -> "Slave.Compiz" "Slave.Layer-3" -> "Slave.Compiz" "Slave.Scaler-0" -> "Slave.Compiz" "Slave.Scaler-1" -> "Slave.Compiz" } subgraph cluster_pipeline_master { style=dashed label="Master Pipeline_A" node [shape=box] { node [bgcolor=grey style=dashed] "Scaler-0"; "Scaler-1"; "Scaler-0/1" } node [bgcolor=grey style=filled] "Layer-0" -> "Scaler-0" "Layer-1" -> "Scaler-0" "Layer-2" -> "Scaler-1" "Layer-3" -> "Scaler-1" "Slave.Compiz" -> "Compiz" "Layer-0" -> "Compiz" "Layer-1" -> "Compiz" "Layer-2" -> "Compiz" "Layer-3" -> "Compiz" "Scaler-0" -> "Compiz" "Scaler-1" -> "Compiz" "Compiz" -> "Scaler-0/1" -> "Wb_layer" "Compiz" -> "Improc" -> "Timing Controller" } "Wb_layer" -> "Memory" "Timing Controller" -> "Monitor"}Slave pipeline enabled data flow¶
Sub-pipelines for input and output¶
A complete display pipeline can be easily divided into three sub-pipelinesaccording to the in/out usage.
Layer(input) pipeline¶
digraph layer_data_flow { rankdir=LR; node [shape=box] { node [bgcolor=grey style=dashed] "Scaler-n"; } "Layer-n" -> "Scaler-n" -> "Compiz"}Layer (input) data flow¶
digraph layer_data_flow { rankdir=LR; node [shape=box] "Layer-0/1" -> "Scaler-0" -> "Merger" "Layer-2/3" -> "Scaler-1" -> "Merger" "Merger" -> "Compiz"}Layer Split pipeline¶
Writeback(output) pipeline¶
digraph writeback_data_flow { rankdir=LR; node [shape=box] { node [bgcolor=grey style=dashed] "Scaler-n"; } "Compiz" -> "Scaler-n" -> "Wb_layer"}Writeback(output) data flow¶
digraph writeback_data_flow { rankdir=LR; node [shape=box] "Compiz" -> "Splitter" "Splitter" -> "Scaler-0" -> "Merger" "Splitter" -> "Scaler-1" -> "Merger" "Merger" -> "Wb_layer"}Writeback(output) Split data flow¶
Display output pipeline¶
digraph single_ppl { rankdir=LR; node [shape=box] "Compiz" -> "Improc" -> "Timing Controller"}display output data flow¶
In the following section we’ll see these three sub-pipelines will be handledby KMS-plane/wb_conn/crtc respectively.
Komeda Resource abstraction¶
struct komeda_pipeline/component¶
To fully utilize and easily access/configure the HW, the driver side also usesa similar architecture: Pipeline/Component to describe the HW features andcapabilities, and a specific component includes two parts:
Data flow controlling.
Specific component capabilities and features.
So the driver defines a common headerstructkomeda_component to describe thedata flow control and all specific components are a subclass of this basestructure.
- structkomeda_component¶
Definition:
struct komeda_component { struct drm_private_obj obj; struct komeda_pipeline *pipeline; char name[32]; u32 __iomem *reg; u32 id; u32 hw_id; u8 max_active_inputs; u8 max_active_outputs; u32 supported_inputs; u32 supported_outputs; const struct komeda_component_funcs *funcs;};Members
objtreat component as private obj
pipelinethe komeda pipeline this component belongs to
namecomponent name
regcomponent register base,which is initialized by chip and used by chip only
idcomponent id
hw_idcomponent hw id,which is initialized by chip and used by chip only
max_active_inputsmax_active_outputs:
maximum number of inputs/outputs that can be active at the same timeNote:the number isn’t the bit number ofsupported_inputs orsupported_outputs, but may be less than it, since component may notsupport enabling allsupported_inputs/outputs at the same time.
max_active_outputsmaximum number of outputs
supported_inputssupported_outputs:
bitmask of BIT(component->id) for the supported inputs/outputs,describes the possibilities of how a component is linked into apipeline.
supported_outputsbitmask of supported output componenet ids
funcschip functions to access HW
Description
structkomeda_component describe the data flow capabilities for how to link acomponent into the display pipeline.all specified components are subclass of this structure.
- structkomeda_component_output¶
Definition:
struct komeda_component_output { struct komeda_component *component; u8 output_port;};Members
componentindicate which component the data comes from
output_portthe output port of the
komeda_component_output.component
Description
a component has multiple outputs, if want to know where the datacomes from, only know the component is not enough, we still need to knowits output port
- structkomeda_component_state¶
Definition:
struct komeda_component_state { struct drm_private_state obj; struct komeda_component *component; union { struct drm_crtc *crtc; struct drm_plane *plane; struct drm_connector *wb_conn; void *binding_user; }; u16 active_inputs; u16 changed_active_inputs; u16 affected_inputs; struct komeda_component_output inputs[KOMEDA_COMPONENT_N_INPUTS];};Members
objtracking component_state by drm_atomic_state
componentbackpointer to the component
{unnamed_union}anonymous
crtcbackpointer for user crtc
planebackpointer for user plane
wb_connbackpointer for user wb_connector
binding_usercurrently bound user, the user can becrtc,plane orwb_conn,which is valid decided bycomponent andinputs
Layer: its user always is plane.
compiz/improc/timing_ctrlr: the user is crtc.
wb_layer: wb_conn;
scaler: plane when input is layer, wb_conn if input is compiz.
active_inputsactive_inputs is bitmask ofinputs index
active_inputs = changed_active_inputs | unchanged_active_inputs
affected_inputs = old->active_inputs | new->active_inputs;
disabling_inputs = affected_inputs ^ active_inputs;
changed_inputs = disabling_inputs | changed_active_inputs;
NOTE:changed_inputs doesn’t include all active_input but onlychanged_active_inputs, and this bitmask can be used in chiplevel for dirty update.
changed_active_inputsbitmask of the changedactive_inputs
affected_inputsbitmask for affectedinputs
inputsthe specific inputs[i] only valid on BIT(i) has been set inactive_inputs, if not the inputs[i] is undefined.
Description
component_state is the data flow configuration of the component, and it’sthe superclass of all specific component_state likekomeda_layer_state,komeda_scaler_state
- structkomeda_pipeline¶
Definition:
struct komeda_pipeline { struct drm_private_obj obj; struct komeda_dev *mdev; struct clk *pxlclk; int id; u32 avail_comps; u32 standalone_disabled_comps; int n_layers; struct komeda_layer *layers[KOMEDA_PIPELINE_MAX_LAYERS]; int n_scalers; struct komeda_scaler *scalers[KOMEDA_PIPELINE_MAX_SCALERS]; struct komeda_compiz *compiz; struct komeda_splitter *splitter; struct komeda_merger *merger; struct komeda_layer *wb_layer; struct komeda_improc *improc; struct komeda_timing_ctrlr *ctrlr; const struct komeda_pipeline_funcs *funcs; struct device_node *of_node; struct device_node *of_output_port; struct device_node *of_output_links[2]; bool dual_link;};Members
objlink pipeline as private obj of drm_atomic_state
mdevthe parent komeda_dev
pxlclkpixel clock
idpipeline id
avail_compsavailable components mask of pipeline
standalone_disabled_compsWhen disable the pipeline, some components can not be disabledtogether with others, but need a sparated and standalone disable.The standalone_disabled_comps are the components which need to bedisabled standalone, and this concept also introduce concept oftwo phase.phase 1: for disabling the common components.phase 2: for disabling the standalong_disabled_comps.
n_layersthe number of layer onlayers
layersthe pipeline layers
n_scalersthe number of scaler onscalers
scalersthe pipeline scalers
compizcompositor
splitterfor split the compiz output to two half data flows
mergermerger
wb_layerwriteback layer
improcpost image processor
ctrlrtiming controller
funcschip private pipeline functions
of_nodepipeline dt node
of_output_portpipeline output port
of_output_linksoutput connector device nodes
dual_linktrue if of_output_links[0] and [1] are both valid
Description
Represent a complete display pipeline and hold all functional components.
- structkomeda_pipeline_state¶
Definition:
struct komeda_pipeline_state { struct drm_private_state obj; struct komeda_pipeline *pipe; struct drm_crtc *crtc; u32 active_comps;};Members
objtracking pipeline_state by drm_atomic_state
pipebackpointer to the pipeline
crtccurrently bound crtc
active_compsbitmask - BIT(component->id) of active components
NOTE
Unlike the pipeline, pipeline_state doesn’t gather any component_stateinto it. It because all component will be managed by drm_atomic_state.
Resource discovery and initialization¶
Pipeline and component are used to describe how to handle the pixel data. Westill need a @structkomeda_dev to describe the whole view of the device, andthe control-abilites of device.
We have &komeda_dev, &komeda_pipeline, &komeda_component. Now fill devices withpipelines. Since komeda is not for D71 only but also intended for later products,of course we’d better share as much as possible between different products. Toachieve this, split the komeda device into two layers: CORE and CHIP.
CORE: for common features and capabilities handling.
CHIP: for register programming and HW specific feature (limitation) handling.
CORE can access CHIP by three chip function structures:
structkomeda_pipeline_funcsstructkomeda_component_funcs
- structkomeda_dev_funcs¶
Definition:
struct komeda_dev_funcs { void (*init_format_table)(struct komeda_dev *mdev); int (*enum_resources)(struct komeda_dev *mdev); void (*cleanup)(struct komeda_dev *mdev); int (*connect_iommu)(struct komeda_dev *mdev); int (*disconnect_iommu)(struct komeda_dev *mdev); irqreturn_t (*irq_handler)(struct komeda_dev *mdev, struct komeda_events *events); int (*enable_irq)(struct komeda_dev *mdev); int (*disable_irq)(struct komeda_dev *mdev); void (*on_off_vblank)(struct komeda_dev *mdev, int master_pipe, bool on); void (*dump_register)(struct komeda_dev *mdev, struct seq_file *seq); int (*change_opmode)(struct komeda_dev *mdev, int new_mode); void (*flush)(struct komeda_dev *mdev, int master_pipe, u32 active_pipes);};Members
init_format_tableinitialize
komeda_dev->format_table, this function should be calledbefore theenum_resourceenum_resourcesfor CHIP to report or add pipeline and component resources to CORE
cleanupcall to chip to cleanup komeda_dev->chip data
connect_iommuOptional, connect to external iommu
disconnect_iommuOptional, disconnect to external iommu
irq_handlerfor CORE to get the HW event from the CHIP when interrupt happened.
enable_irqenable irq
disable_irqdisable irq
on_off_vblanknotify HW to on/off vblank
dump_registerOptional, dump registers to seq_file
change_opmodeNotify HW to switch to a new display operation mode.
flushNotify the HW to flush or kickoff the update
Description
Supplied by chip level and returned by the chip entry function xxx_identify,
- structkomeda_dev¶
Definition:
struct komeda_dev { struct device *dev; u32 __iomem *reg_base; struct komeda_chip_info chip; struct komeda_format_caps_table fmt_tbl; struct clk *aclk; int irq; struct mutex lock; u32 dpmode; int n_pipelines; struct komeda_pipeline *pipelines[KOMEDA_MAX_PIPELINES]; const struct komeda_dev_funcs *funcs; void *chip_data; struct iommu_domain *iommu; struct dentry *debugfs_root; u16 err_verbosity;#define KOMEDA_DEV_PRINT_ERR_EVENTS BIT(0);#define KOMEDA_DEV_PRINT_WARN_EVENTS BIT(1);#define KOMEDA_DEV_PRINT_INFO_EVENTS BIT(2);#define KOMEDA_DEV_PRINT_DUMP_STATE_ON_EVENT BIT(8);#define KOMEDA_DEV_PRINT_DISABLE_RATELIMIT BIT(12);};Members
devthe base device structure
reg_basethe base address of komeda io space
chipthe basic chip information
fmt_tblinitialized by
komeda_dev_funcs->init_format_tableaclkHW main engine clk
irqirq number
lockused to protect dpmode
dpmodecurrent display mode
n_pipelinesthe number of pipe inpipelines
pipelinesthe komeda pipelines
funcschip funcs to access to HW
chip_datachip data will be added by
komeda_dev_funcs.enum_resources()anddestroyed bykomeda_dev_funcs.cleanup()iommuiommu domain
debugfs_rootroot directory of komeda debugfs
err_verbositybitmask for how much extra info to print on error
See KOMEDA_DEV_* macros for details. Low byte contains the debuglevel categories, the high byte contains extra debug options.
Description
Pipeline and component are used to describe how to handle the pixel data.komeda_device is for describing the whole view of the device, and thecontrol-abilites of device.
Format handling¶
- structkomeda_format_caps¶
Definition:
struct komeda_format_caps { u32 hw_id; u32 fourcc; u32 supported_layer_types; u32 supported_rots; u32 supported_afbc_layouts; u64 supported_afbc_features;};Members
hw_idhw format id, hw specific value.
fourccdrm fourcc format.
supported_layer_typesindicate which layer supports this format
supported_rotsallowed rotations for this format
supported_afbc_layoutssupported afbc layerout
supported_afbc_featuressupported afbc features
Description
komeda_format_caps is for describing ARM display specific features andlimitations for a specific format, and format_caps will be linked intokomeda_framebuffer like a extension ofdrm_format_info.
NOTE
one fourcc may has two different format_caps items for fourcc andfourcc+modifier
- structkomeda_format_caps_table¶
format_caps mananger
Definition:
struct komeda_format_caps_table { u32 n_formats; const struct komeda_format_caps *format_caps; bool (*format_mod_supported)(const struct komeda_format_caps *caps, u32 layer_type, u64 modifier, u32 rot);};Members
n_formatsthe size of format_caps list.
format_capsformat_caps list.
format_mod_supportedOptional. Some HW may have special requirements orlimitations which can not be described by format_caps, this func supply HWthe ability to do the further HW specific check.
- structkomeda_fb¶
Entending drm_framebuffer with komeda attribute
Definition:
struct komeda_fb { struct drm_framebuffer base; const struct komeda_format_caps *format_caps; bool is_va; u32 aligned_w; u32 aligned_h; u32 afbc_size; u32 offset_payload;};Members
baseformat_capsextends drm_format_info for komeda specific information
is_vaif smmu is enabled, it will be true
aligned_waligned frame buffer width
aligned_haligned frame buffer height
afbc_sizeminimum size of afbc
offset_payloadstart of afbc body buffer
Attach komeda_dev to DRM-KMS¶
Komeda abstracts resources by pipeline/component, but DRM-KMS usescrtc/plane/connector. One KMS-obj cannot represent only one single component,since the requirements of a single KMS object cannot simply be achieved by asingle component, usually that needs multiple components to fit the requirement.Like set mode, gamma, ctm for KMS all target on CRTC-obj, but komeda needscompiz, improc and timing_ctrlr to work together to fit these requirements.And a KMS-Plane may require multiple komeda resources: layer/scaler/compiz.
So, one KMS-Obj represents a sub-pipeline of komeda resources.
Plane:Layer(input) pipeline
Wb_connector:Writeback(output) pipeline
So, for komeda, we treat KMS crtc/plane/connector as users of pipeline andcomponent, and at any one time a pipeline/component only can be used by oneuser. And pipeline/component will be treated as private object of DRM-KMS; thestate will be managed by drm_atomic_state as well.
How to map plane to Layer(input) pipeline¶
Komeda has multiple Layer input pipelines, see:-Single pipeline data flow-Dual pipeline with Slave enabled
The easiest way is binding a plane to a fixed Layer pipeline, but consider thekomeda capabilities:
Layer Split, SeeLayer(input) pipeline
Layer_Split is quite complicated feature, which splits a big image into twoparts and handles it by two layers and two scalers individually. But itimports an edge problem or effect in the middle of the image after the split.To avoid such a problem, it needs a complicated Split calculation and somespecial configurations to the layer and scaler. We’d better hide such HWrelated complexity to user mode.
Slave pipeline, SeeDual pipeline with Slave enabled
Since the compiz component doesn’t output alpha value, the slave pipelineonly can be used for bottom layers composition. The komeda driver wants tohide this limitation to the user. The way to do this is to pick a suitableLayer according to plane_state->zpos.
So for komeda, the KMS-plane doesn’t represent a fixed komeda layer pipeline,but multiple Layers with same capabilities. Komeda will select one or moreLayers to fit the requirement of one KMS-plane.
Make component/pipeline to be drm_private_obj¶
Adddrm_private_obj tokomeda_component,komeda_pipeline
structkomeda_component{structdrm_private_objobj;...}structkomeda_pipeline{structdrm_private_objobj;...}
Tracking component_state/pipeline_state by drm_atomic_state¶
Adddrm_private_state and user tokomeda_component_state,komeda_pipeline_state
structkomeda_component_state{structdrm_private_stateobj;void*binding_user;...}structkomeda_pipeline_state{structdrm_private_stateobj;structdrm_crtc*crtc;...}
komeda component validation¶
Komeda has multiple types of components, but the process of validation aresimilar, usually including the following steps:
intkomeda_xxxx_validate(structkomeda_component_xxxxxx_comp,structkomeda_component_output*input_dflow,structdrm_plane/crtc/connector*user,structdrm_plane/crtc/connector_state,*user_state){setup1:checkifcomponentisneeded,likethescalerisoptionaldependingontheuser_state;ifunneeded,justreturn,andthecallerwillputthedataflowintonextstage.Setup2:checkuser_statewithcomponentfeaturesandcapabilitiestoseeifrequirementscanbemet;ifnot,returnfail.Setup3:getcomponent_statefromdrm_atomic_state,andtrysettosetusertocomponent;failifcomponenthasbeenassignedtoanotheruseralready.Setup3:configurethecomponent_state,likesetitsinputcomponent,convertuser_statetocomponentspecificstate.Setup4:adjusttheinput_dflowandprepareitforthenextstage.}
komeda_kms Abstraction¶
- structkomeda_plane¶
komeda instance of drm_plane
Definition:
struct komeda_plane { struct drm_plane base; struct komeda_layer *layer;};Members
baselayerrepresents available layer input pipelines for this plane.
NOTE:the layer is not for a specific Layer, but indicate a group ofLayers with same capabilities.
- structkomeda_plane_state¶
Definition:
struct komeda_plane_state { struct drm_plane_state base; struct list_head zlist_node; u8 layer_split : 1;};Members
basezlist_nodezorder list node
layer_spliton/off layer_split
Description
The plane_state can be split into two data flow (left/right) and handledby two layerskomeda_plane.layer andkomeda_plane.layer.right
- structkomeda_wb_connector¶
Definition:
struct komeda_wb_connector { struct drm_writeback_connector base; struct komeda_layer *wb_layer;};Members
basewb_layerrepresents associated writeback pipeline of komeda
- structkomeda_crtc¶
Definition:
struct komeda_crtc { struct drm_crtc base; struct komeda_pipeline *master; struct komeda_pipeline *slave; u32 slave_planes; struct komeda_wb_connector *wb_conn; struct completion *disable_done; struct drm_encoder encoder;};Members
basemasteronly master has display output
slaveoptional
Doesn’t have its own display output, the handled data flow willmerge into the master.
slave_planeskomeda slave planes mask
wb_connkomeda write back connector
disable_donethis flip_done is for tracing the disable
encoderencoder at the end of the pipeline
- structkomeda_crtc_state¶
Definition:
struct komeda_crtc_state { struct drm_crtc_state base; u32 affected_pipes; u32 active_pipes; u64 clock_ratio; u32 max_slave_zorder;};Members
baseaffected_pipesthe affected pipelines in once display instance
active_pipesthe active pipelines in once display instance
clock_ratioratio of (aclk << 32)/pxlclk
max_slave_zorderthe maximum of slave zorder
komde_kms Functions¶
- intkomeda_crtc_atomic_check(structdrm_crtc*crtc,structdrm_atomic_state*state)¶
build display output data flow
Parameters
structdrm_crtc*crtcDRM crtc
structdrm_atomic_state*statethe crtc state object
Description
crtc_atomic_check is the final check stage, so beside build a display datapipeline according to the crtc_state, but still needs to release or disablethe unclaimed pipeline resources.
Return
Zero for success or -errno
- intkomeda_plane_atomic_check(structdrm_plane*plane,structdrm_atomic_state*state)¶
build input data flow
Parameters
structdrm_plane*planeDRM plane
structdrm_atomic_state*statethe plane state object
Return
Zero for success or -errno
Build komeda to be a Linux module driver¶
Now we have two level devices:
komeda_dev: describes the real display hardware.
komeda_kms_dev: attaches or connects komeda_dev to DRM-KMS.
All komeda operations are supplied or operated by komeda_dev or komeda_kms_dev,the module driver is only a simple wrapper to pass the Linux command(probe/remove/pm) into komeda_dev or komeda_kms_dev.