Skip to content

Commit dbb32d8

Browse files
Liu YingMarek Vasut
authored andcommitted
drm: lcdif: Add multiple encoders and first bridges support
The single LCDIF embedded in i.MX93 SoC may drive multiple displays simultaneously. Look at LCDIF output port's remote port parents to find all enabled first bridges. Add an encoder for each found bridge and attach the bridge to the encoder. This is a preparation for adding i.MX93 LCDIF support. Tested-by: Alexander Stein <alexander.stein@ew.tq-group.com> Acked-by: Alexander Stein <alexander.stein@ew.tq-group.com> Signed-off-by: Liu Ying <victor.liu@nxp.com> Reviewed-by: Marek Vasut <marex@denx.de> Signed-off-by: Marek Vasut <marex@denx.de> Link: https://patchwork.freedesktop.org/patch/msgid/20230510092450.4024730-6-victor.liu@nxp.com
1 parent c62a7b9 commit dbb32d8

3 files changed

Lines changed: 65 additions & 28 deletions

File tree

drivers/gpu/drm/mxsfb/lcdif_drv.c

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
#include <linux/dma-mapping.h>
1010
#include <linux/io.h>
1111
#include <linux/module.h>
12+
#include <linux/of.h>
1213
#include <linux/of_device.h>
14+
#include <linux/of_graph.h>
1315
#include <linux/platform_device.h>
1416
#include <linux/pm_runtime.h>
1517

1618
#include <drm/drm_atomic_helper.h>
1719
#include <drm/drm_bridge.h>
1820
#include <drm/drm_drv.h>
21+
#include <drm/drm_encoder.h>
1922
#include <drm/drm_fbdev_dma.h>
2023
#include <drm/drm_gem_dma_helper.h>
2124
#include <drm/drm_gem_framebuffer_helper.h>
@@ -38,19 +41,70 @@ static const struct drm_mode_config_helper_funcs lcdif_mode_config_helpers = {
3841
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
3942
};
4043

44+
static const struct drm_encoder_funcs lcdif_encoder_funcs = {
45+
.destroy = drm_encoder_cleanup,
46+
};
47+
4148
static int lcdif_attach_bridge(struct lcdif_drm_private *lcdif)
4249
{
43-
struct drm_device *drm = lcdif->drm;
50+
struct device *dev = lcdif->drm->dev;
51+
struct device_node *ep;
4452
struct drm_bridge *bridge;
4553
int ret;
4654

47-
bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
48-
if (IS_ERR(bridge))
49-
return PTR_ERR(bridge);
50-
51-
ret = drm_bridge_attach(&lcdif->encoder, bridge, NULL, 0);
52-
if (ret)
53-
return dev_err_probe(drm->dev, ret, "Failed to attach bridge\n");
55+
for_each_endpoint_of_node(dev->of_node, ep) {
56+
struct device_node *remote;
57+
struct of_endpoint of_ep;
58+
struct drm_encoder *encoder;
59+
60+
remote = of_graph_get_remote_port_parent(ep);
61+
if (!of_device_is_available(remote)) {
62+
of_node_put(remote);
63+
continue;
64+
}
65+
of_node_put(remote);
66+
67+
ret = of_graph_parse_endpoint(ep, &of_ep);
68+
if (ret < 0) {
69+
dev_err(dev, "Failed to parse endpoint %pOF\n", ep);
70+
of_node_put(ep);
71+
return ret;
72+
}
73+
74+
bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, of_ep.id);
75+
if (IS_ERR(bridge)) {
76+
of_node_put(ep);
77+
return dev_err_probe(dev, PTR_ERR(bridge),
78+
"Failed to get bridge for endpoint%u\n",
79+
of_ep.id);
80+
}
81+
82+
encoder = devm_kzalloc(dev, sizeof(*encoder), GFP_KERNEL);
83+
if (!encoder) {
84+
dev_err(dev, "Failed to allocate encoder for endpoint%u\n",
85+
of_ep.id);
86+
of_node_put(ep);
87+
return -ENOMEM;
88+
}
89+
90+
encoder->possible_crtcs = drm_crtc_mask(&lcdif->crtc);
91+
ret = drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
92+
DRM_MODE_ENCODER_NONE, NULL);
93+
if (ret) {
94+
dev_err(dev, "Failed to initialize encoder for endpoint%u: %d\n",
95+
of_ep.id, ret);
96+
of_node_put(ep);
97+
return ret;
98+
}
99+
100+
ret = drm_bridge_attach(encoder, bridge, NULL, 0);
101+
if (ret) {
102+
of_node_put(ep);
103+
return dev_err_probe(dev, ret,
104+
"Failed to attach bridge for endpoint%u\n",
105+
of_ep.id);
106+
}
107+
}
54108

55109
return 0;
56110
}

drivers/gpu/drm/mxsfb/lcdif_drv.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
#include <drm/drm_bridge.h>
1212
#include <drm/drm_crtc.h>
1313
#include <drm/drm_device.h>
14-
#include <drm/drm_encoder.h>
1514
#include <drm/drm_plane.h>
1615

1716
struct clk;
@@ -30,7 +29,6 @@ struct lcdif_drm_private {
3029
/* i.MXRT does support overlay planes, add them here. */
3130
} planes;
3231
struct drm_crtc crtc;
33-
struct drm_encoder encoder;
3432
};
3533

3634
static inline struct lcdif_drm_private *

drivers/gpu/drm/mxsfb/lcdif_kms.c

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -659,14 +659,6 @@ static const struct drm_crtc_funcs lcdif_crtc_funcs = {
659659
.disable_vblank = lcdif_crtc_disable_vblank,
660660
};
661661

662-
/* -----------------------------------------------------------------------------
663-
* Encoder
664-
*/
665-
666-
static const struct drm_encoder_funcs lcdif_encoder_funcs = {
667-
.destroy = drm_encoder_cleanup,
668-
};
669-
670662
/* -----------------------------------------------------------------------------
671663
* Planes
672664
*/
@@ -759,7 +751,6 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
759751
BIT(DRM_COLOR_YCBCR_BT2020);
760752
const u32 supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) |
761753
BIT(DRM_COLOR_YCBCR_FULL_RANGE);
762-
struct drm_encoder *encoder = &lcdif->encoder;
763754
struct drm_crtc *crtc = &lcdif->crtc;
764755
int ret;
765756

@@ -783,13 +774,7 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
783774
return ret;
784775

785776
drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs);
786-
ret = drm_crtc_init_with_planes(lcdif->drm, crtc,
787-
&lcdif->planes.primary, NULL,
788-
&lcdif_crtc_funcs, NULL);
789-
if (ret)
790-
return ret;
791-
792-
encoder->possible_crtcs = drm_crtc_mask(crtc);
793-
return drm_encoder_init(lcdif->drm, encoder, &lcdif_encoder_funcs,
794-
DRM_MODE_ENCODER_NONE, NULL);
777+
return drm_crtc_init_with_planes(lcdif->drm, crtc,
778+
&lcdif->planes.primary, NULL,
779+
&lcdif_crtc_funcs, NULL);
795780
}

0 commit comments

Comments
 (0)