aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/mcde/mcde_drv.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2020-11-12 15:29:25 +0100
committerLinus Walleij <linus.walleij@linaro.org>2020-11-24 00:09:08 +0100
commitd795fd322063246f23ca20ba0125cf3ed89cc1d3 (patch)
tree6d3801ca4d0c614c89e3048e4aabc6f92a7e0dc5 /drivers/gpu/drm/mcde/mcde_drv.c
parentbfbc5e3b1774073ec92129995c7a6291015008af (diff)
downloadlinux-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.c46
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) {