Introduction
The relationship of host driver and panel driver is introduced here. The design is a very good example of a design pattern: aggregation or facade. Declaimer: this document is not a complete reference document for the drivers, but just a notes to understand from one perspective.
Concepts
MIPI DSI Host Driver
What is the host? The host basically means the SOC itself. The MIPI Host driver is in e.g.:
drivers/gpu/drm/rockchip/dw-mipi-dsi.c
It controls the registers in SOC in order to connect to a panel.
MIPI Panel Driver
What is the panel? It basically means the Panel, which could be controlled BY SoC via communication channels, for example in case of MIPI DSI, the host could control the panel by DSI commands via D0.
Connector
A connector is an aggregate concept
. The separation of Host driver
and
Panel driver
is for decoupling the two logic parts. However it might be
confusing for the client of host driver and panel driver, as the client just
how to show
or display
. A connector
is an aggregation of two logical
parts and expose only one interface to the client.
How these two drivers are bound together
So how these two driver interact with each other? This is no magic here, it
is done via callbacks/registrations. Specifically, it is done via component
.
Refer to
link for
the details of concept of component
:
In short, component allows to aggregate drivers into an aggregated driver. In our case, it helps to aggregate the MIPI DSI host driver and sub-dev panel driver.
In a bit more details, the host driver register its self as a component, once
it is done, the bind
callback will be called by the component
system. In
this bind
callback, the host driver will try to do the binding with its
panel driver.
More details
The design of component
is quite simple but powerful. It allows the host
driver and panel driver to become more static, but move the dynamic part under
the cover of component
helper system.
probing of host driver
During probe of MIPI DSI Host driver, following component (ops) is registered:
ret = component_add(dev, &dw_mipi_dsi_ops);
The host DSI ops has two callback functions: bind
and unbind
.
static const struct component_ops dw_mipi_dsi_ops = {
.bind = dw_mipi_dsi_bind,
.unbind = dw_mipi_dsi_unbind,
};
Component calling bind
callback
In this binding function it will check if the panel driver is available. If
not, it will return EPROBE_DEFER
to indicate the component
system that
‘please call me later’. The component system will call it again a bit later.
Following function is called to check if the panel is available:
dsi->panel = of_drm_find_panel(dsi->client);
of_drm_find_panel
is a helper function to check if the panel is already added
by function drm_panel_add
, which is called by panel driver during probing.
Refer to:
drivers/gpu/drm/drm_panel.c
probing of panel driver
Refer to following source code for for the calling of drm_panel_add
by the
panel driver:
drivers/gpu/drm/panel/panel-simple.c
continuing of probing of Host driver
Once the host driver (in binding function) find the correct panel, it will
continue its logic, it will other factors and it may tell to be called later
again by return -EPROBE_DEFER
.
Refer to a specific host driver:
drivers/gpu/drm/rockchip/dw-mipi-dsi.c
connector
get_modes
As we understand earlier, connector
will expose some functions. One of them
is get_modes
function, as shown in below:
static const struct drm_connector_helper_funcs
dw_mipi_dsi_connector_helper_funcs = {
.get_modes = dw_mipi_dsi_connector_get_modes,
.best_encoder = dw_mipi_dsi_connector_best_encoder,
};
It will call the panel’s driver’s function eventually:
int panel_simple_get_modes(struct drm_panel *panel)
encoder
Another part of a connector
is the encoder, the encoder has several callbacks
to be used by the client:
static const struct drm_encoder_helper_funcs
dw_mipi_dsi_encoder_helper_funcs = {
.loader_protect = dw_mipi_dsi_encoder_loader_protect,
.mode_set = dw_mipi_dsi_encoder_mode_set,
.enable = dw_mipi_dsi_encoder_enable,
.disable = dw_mipi_dsi_encoder_disable,
.atomic_check = dw_mipi_dsi_encoder_atomic_check,
};
Initialization Steps
- DSI Encoder Enabled (Set the Lane/Clock)
- Set the VoP routing to DSI
- Set the DSI to command mode
- Toggle Panel’s Reset pin and Enable pin to activate panel (for receiving commands)
- After some delay, send init-sequence commands
- Set the DSI to video mode (so DSI could output video packets)
- Enable Panel’s backlight
Summary
The aggregation
design patten allows logic separation of host driver and
panel driver. While facade
design patten allows an unified interface to the
client.