Skip to content

Commit c3bf8e2

Browse files
Sankeerth Billakantilumag
authored andcommitted
drm/msm/dp: Add eDP support via aux_bus
This patch adds support for generic eDP sink through aux_bus. The eDP/DP controller driver should support aux transactions originating from the panel-edp driver and hence should be initialized and ready. The panel bridge supporting the panel should be ready before the bridge connector is initialized. The generic panel probe needs the controller resources to be enabled to support the aux transactions originating from the panel probe. Signed-off-by: Sankeerth Billakanti <[email protected]> Reviewed-by: Douglas Anderson <[email protected]> Reviewed-by: Stephen Boyd <[email protected]> Patchwork: https://patchwork.freedesktop.org/patch/483307/ Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent 375a126 commit c3bf8e2

File tree

5 files changed

+101
-29
lines changed

5 files changed

+101
-29
lines changed

drivers/gpu/drm/msm/dp/dp_display.c

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/component.h>
1111
#include <linux/of_irq.h>
1212
#include <linux/delay.h>
13+
#include <drm/dp/drm_dp_aux_bus.h>
1314

1415
#include "msm_drv.h"
1516
#include "msm_kms.h"
@@ -263,13 +264,12 @@ static int dp_display_bind(struct device *dev, struct device *master,
263264
dp->dp_display.drm_dev = drm;
264265
priv->dp[dp->id] = &dp->dp_display;
265266

266-
rc = dp->parser->parse(dp->parser, dp->dp_display.connector_type);
267+
rc = dp->parser->parse(dp->parser);
267268
if (rc) {
268269
DRM_ERROR("device tree parsing failed\n");
269270
goto end;
270271
}
271272

272-
dp->dp_display.next_bridge = dp->parser->next_bridge;
273273

274274
dp->drm_dev = drm;
275275
dp->aux->drm_dev = drm;
@@ -1288,6 +1288,8 @@ static int dp_display_probe(struct platform_device *pdev)
12881288
dp->name = "drm_dp";
12891289
dp->dp_display.connector_type = desc->connector_type;
12901290
dp->wide_bus_en = desc->wide_bus_en;
1291+
dp->dp_display.is_edp =
1292+
(dp->dp_display.connector_type == DRM_MODE_CONNECTOR_eDP);
12911293

12921294
rc = dp_init_sub_modules(dp);
12931295
if (rc) {
@@ -1481,7 +1483,8 @@ void msm_dp_irq_postinstall(struct msm_dp *dp_display)
14811483

14821484
dp = container_of(dp_display, struct dp_display_private, dp_display);
14831485

1484-
dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
1486+
if (!dp_display->is_edp)
1487+
dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 100);
14851488
}
14861489

14871490
bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
@@ -1512,6 +1515,64 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
15121515
}
15131516
}
15141517

1518+
static int dp_display_get_next_bridge(struct msm_dp *dp)
1519+
{
1520+
int rc;
1521+
struct dp_display_private *dp_priv;
1522+
struct device_node *aux_bus;
1523+
struct device *dev;
1524+
1525+
dp_priv = container_of(dp, struct dp_display_private, dp_display);
1526+
dev = &dp_priv->pdev->dev;
1527+
aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
1528+
1529+
if (aux_bus && dp->is_edp) {
1530+
dp_display_host_init(dp_priv);
1531+
dp_catalog_ctrl_hpd_config(dp_priv->catalog);
1532+
dp_display_host_phy_init(dp_priv);
1533+
enable_irq(dp_priv->irq);
1534+
1535+
/*
1536+
* The code below assumes that the panel will finish probing
1537+
* by the time devm_of_dp_aux_populate_ep_devices() returns.
1538+
* This isn't a great assumption since it will fail if the
1539+
* panel driver is probed asynchronously but is the best we
1540+
* can do without a bigger driver reorganization.
1541+
*/
1542+
rc = devm_of_dp_aux_populate_ep_devices(dp_priv->aux);
1543+
of_node_put(aux_bus);
1544+
if (rc)
1545+
goto error;
1546+
} else if (dp->is_edp) {
1547+
DRM_ERROR("eDP aux_bus not found\n");
1548+
return -ENODEV;
1549+
}
1550+
1551+
/*
1552+
* External bridges are mandatory for eDP interfaces: one has to
1553+
* provide at least an eDP panel (which gets wrapped into panel-bridge).
1554+
*
1555+
* For DisplayPort interfaces external bridges are optional, so
1556+
* silently ignore an error if one is not present (-ENODEV).
1557+
*/
1558+
rc = dp_parser_find_next_bridge(dp_priv->parser);
1559+
if (!dp->is_edp && rc == -ENODEV)
1560+
return 0;
1561+
1562+
if (!rc) {
1563+
dp->next_bridge = dp_priv->parser->next_bridge;
1564+
return 0;
1565+
}
1566+
1567+
error:
1568+
if (dp->is_edp) {
1569+
disable_irq(dp_priv->irq);
1570+
dp_display_host_phy_exit(dp_priv);
1571+
dp_display_host_deinit(dp_priv);
1572+
}
1573+
return rc;
1574+
}
1575+
15151576
int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
15161577
struct drm_encoder *encoder)
15171578
{
@@ -1535,6 +1596,10 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
15351596

15361597
dp_display->encoder = encoder;
15371598

1599+
ret = dp_display_get_next_bridge(dp_display);
1600+
if (ret)
1601+
return ret;
1602+
15381603
dp_display->bridge = dp_bridge_init(dp_display, dev, encoder);
15391604
if (IS_ERR(dp_display->bridge)) {
15401605
ret = PTR_ERR(dp_display->bridge);

drivers/gpu/drm/msm/dp/dp_display.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct msm_dp {
2121
bool audio_enabled;
2222
bool power_on;
2323
unsigned int connector_type;
24+
bool is_edp;
2425

2526
hdmi_codec_plugged_cb plugged_cb;
2627

drivers/gpu/drm/msm/dp/dp_drm.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,23 @@ struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *
8787
bridge->funcs = &dp_bridge_ops;
8888
bridge->type = dp_display->connector_type;
8989

90-
bridge->ops =
91-
DRM_BRIDGE_OP_DETECT |
92-
DRM_BRIDGE_OP_HPD |
93-
DRM_BRIDGE_OP_MODES;
90+
/*
91+
* Many ops only make sense for DP. Why?
92+
* - Detect/HPD are used by DRM to know if a display is _physically_
93+
* there, not whether the display is powered on / finished initting.
94+
* On eDP we assume the display is always there because you can't
95+
* know until power is applied. If we don't implement the ops DRM will
96+
* assume our display is always there.
97+
* - Currently eDP mode reading is driven by the panel driver. This
98+
* allows the panel driver to properly power itself on to read the
99+
* modes.
100+
*/
101+
if (!dp_display->is_edp) {
102+
bridge->ops =
103+
DRM_BRIDGE_OP_DETECT |
104+
DRM_BRIDGE_OP_HPD |
105+
DRM_BRIDGE_OP_MODES;
106+
}
94107

95108
drm_bridge_add(bridge);
96109

drivers/gpu/drm/msm/dp/dp_parser.c

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ static int dp_parser_clock(struct dp_parser *parser)
263263
return 0;
264264
}
265265

266-
static int dp_parser_find_next_bridge(struct dp_parser *parser)
266+
int dp_parser_find_next_bridge(struct dp_parser *parser)
267267
{
268268
struct device *dev = &parser->pdev->dev;
269269
struct drm_bridge *bridge;
@@ -277,7 +277,7 @@ static int dp_parser_find_next_bridge(struct dp_parser *parser)
277277
return 0;
278278
}
279279

280-
static int dp_parser_parse(struct dp_parser *parser, int connector_type)
280+
static int dp_parser_parse(struct dp_parser *parser)
281281
{
282282
int rc = 0;
283283

@@ -298,25 +298,6 @@ static int dp_parser_parse(struct dp_parser *parser, int connector_type)
298298
if (rc)
299299
return rc;
300300

301-
/*
302-
* External bridges are mandatory for eDP interfaces: one has to
303-
* provide at least an eDP panel (which gets wrapped into panel-bridge).
304-
*
305-
* For DisplayPort interfaces external bridges are optional, so
306-
* silently ignore an error if one is not present (-ENODEV).
307-
*/
308-
rc = dp_parser_find_next_bridge(parser);
309-
if (rc == -ENODEV) {
310-
if (connector_type == DRM_MODE_CONNECTOR_eDP) {
311-
DRM_ERROR("eDP: next bridge is not present\n");
312-
return rc;
313-
}
314-
} else if (rc) {
315-
if (rc != -EPROBE_DEFER)
316-
DRM_ERROR("DP: error parsing next bridge: %d\n", rc);
317-
return rc;
318-
}
319-
320301
/* Map the corresponding regulator information according to
321302
* version. Currently, since we only have one supported platform,
322303
* mapping the regulator directly.

drivers/gpu/drm/msm/dp/dp_parser.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ struct dp_parser {
125125
u32 max_dp_lanes;
126126
struct drm_bridge *next_bridge;
127127

128-
int (*parse)(struct dp_parser *parser, int connector_type);
128+
int (*parse)(struct dp_parser *parser);
129129
};
130130

131131
/**
@@ -141,4 +141,16 @@ struct dp_parser {
141141
*/
142142
struct dp_parser *dp_parser_get(struct platform_device *pdev);
143143

144+
/**
145+
* dp_parser_find_next_bridge() - find an additional bridge to DP
146+
*
147+
* @parser: dp_parser data from client
148+
*
149+
* This function is used to find any additional bridge attached to
150+
* the DP controller. The eDP interface requires a panel bridge.
151+
*
152+
* Return: 0 if able to get the bridge, otherwise negative errno for failure.
153+
*/
154+
int dp_parser_find_next_bridge(struct dp_parser *parser);
155+
144156
#endif

0 commit comments

Comments
 (0)