diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2020-11-12 15:29:25 +0100 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2020-11-24 00:09:08 +0100 |
commit | d795fd322063246f23ca20ba0125cf3ed89cc1d3 (patch) | |
tree | 6d3801ca4d0c614c89e3048e4aabc6f92a7e0dc5 /drivers/gpu/drm/mcde/mcde_drv.c | |
parent | bfbc5e3b1774073ec92129995c7a6291015008af (diff) | |
download | linux-d795fd322063246f23ca20ba0125cf3ed89cc1d3.tar.gz |
drm/mcde: Support DPI output
This implements support for DPI output using the port node
in the device tree to connect a DPI LCD display to the
MCDE. The block also supports TV-out but we leave that
for another day when we have a hardware using it.
We implement parsing and handling of the "port" node,
and follow that to the DPI endpoint.
The clock divider used by the MCDE to divide down the
"lcdclk" (this has been designed for TV-like frequencies)
is represented by an ordinary clock provider internally
in the MCDE. This idea was inspired by the PL111 solution
by Eric Anholt: the divider also works very similar to
the Pl111 clock divider.
We take care to clear up some errors regarding the number
of available formatters and their type. We have 6 DSI
formatters and 2 DPI formatters.
Tested on the Samsung GT-I9070 Janice mobile phone.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Cc: Stephan Gerhold <stephan@gerhold.net>
Cc: phone-devel@vger.kernel.org
Cc: upstreaming@lists.sr.ht
Link: https://patchwork.freedesktop.org/patch/msgid/20201112142925.2571179-2-linus.walleij@linaro.org
Diffstat (limited to 'drivers/gpu/drm/mcde/mcde_drv.c')
-rw-r--r-- | drivers/gpu/drm/mcde/mcde_drv.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index 870626e04ec0..7196a437952b 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -22,13 +22,13 @@ * The hardware has four display pipes, and the layout is a little * bit like this:: * - * Memory -> Overlay -> Channel -> FIFO -> 5 formatters -> DSI/DPI - * External 0..5 0..3 A,B, 3 x DSI bridge + * Memory -> Overlay -> Channel -> FIFO -> 8 formatters -> DSI/DPI + * External 0..5 0..3 A,B, 6 x DSI bridge * source 0..9 C0,C1 2 x DPI * * FIFOs A and B are for LCD and HDMI while FIFO CO/C1 are for * panels with embedded buffer. - * 3 of the formatters are for DSI. + * 6 of the formatters are for DSI, 3 pairs for VID/CMD respectively. * 2 of the formatters are for DPI. * * Behind the formatters are the DSI or DPI ports that route to @@ -130,9 +130,37 @@ static int mcde_modeset_init(struct drm_device *drm) struct mcde *mcde = to_mcde(drm); int ret; + /* + * If no other bridge was found, check if we have a DPI panel or + * any other bridge connected directly to the MCDE DPI output. + * If a DSI bridge is found, DSI will take precedence. + * + * TODO: more elaborate bridge selection if we have more than one + * thing attached to the system. + */ if (!mcde->bridge) { - dev_err(drm->dev, "no display output bridge yet\n"); - return -EPROBE_DEFER; + struct drm_panel *panel; + struct drm_bridge *bridge; + + ret = drm_of_find_panel_or_bridge(drm->dev->of_node, + 0, 0, &panel, &bridge); + if (ret) { + dev_err(drm->dev, + "Could not locate any output bridge or panel\n"); + return ret; + } + if (panel) { + bridge = drm_panel_bridge_add_typed(panel, + DRM_MODE_CONNECTOR_DPI); + if (IS_ERR(bridge)) { + dev_err(drm->dev, + "Could not connect panel bridge\n"); + return PTR_ERR(bridge); + } + } + mcde->dpi_output = true; + mcde->bridge = bridge; + mcde->flow_mode = MCDE_DPI_FORMATTER_FLOW; } mode_config = &drm->mode_config; @@ -156,13 +184,7 @@ static int mcde_modeset_init(struct drm_device *drm) return ret; } - /* - * Attach the DSI bridge - * - * TODO: when adding support for the DPI bridge or several DSI bridges, - * we selectively connect the bridge(s) here instead of this simple - * attachment. - */ + /* Attach the bridge. */ ret = drm_simple_display_pipe_attach_bridge(&mcde->pipe, mcde->bridge); if (ret) { |