Skip to content

Commit 8d6ef26

Browse files
author
Thomas Zimmermann
committed
drm/ast: Disconnect BMC if physical connector is connected
Many user-space compositors fail with mode setting if a CRTC has more than one connected connector. This is the case with the BMC on Aspeed systems. Work around this problem by setting the BMC's connector status to disconnected when the physical connector has a display attached. This way compositors will only see one connected connector at a time; either the physical one or the BMC. Suggested-by: Jocelyn Falempe <[email protected]> Fixes: e329cb5 ("drm/ast: Add BMC virtual connector") Signed-off-by: Thomas Zimmermann <[email protected]> Cc: <[email protected]> # v6.6+ Reviewed-by: Jocelyn Falempe <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 3f7c063 commit 8d6ef26

File tree

2 files changed

+67
-8
lines changed

2 files changed

+67
-8
lines changed

drivers/gpu/drm/ast/ast_drv.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,17 @@ to_ast_sil164_connector(struct drm_connector *connector)
174174
return container_of(connector, struct ast_sil164_connector, base);
175175
}
176176

177+
struct ast_bmc_connector {
178+
struct drm_connector base;
179+
struct drm_connector *physical_connector;
180+
};
181+
182+
static inline struct ast_bmc_connector *
183+
to_ast_bmc_connector(struct drm_connector *connector)
184+
{
185+
return container_of(connector, struct ast_bmc_connector, base);
186+
}
187+
177188
/*
178189
* Device
179190
*/
@@ -218,7 +229,7 @@ struct ast_device {
218229
} astdp;
219230
struct {
220231
struct drm_encoder encoder;
221-
struct drm_connector connector;
232+
struct ast_bmc_connector bmc_connector;
222233
} bmc;
223234
} output;
224235

drivers/gpu/drm/ast/ast_mode.c

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,13 +1767,38 @@ static const struct drm_encoder_funcs ast_bmc_encoder_funcs = {
17671767
.destroy = drm_encoder_cleanup,
17681768
};
17691769

1770+
static int ast_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
1771+
struct drm_modeset_acquire_ctx *ctx,
1772+
bool force)
1773+
{
1774+
struct ast_bmc_connector *bmc_connector = to_ast_bmc_connector(connector);
1775+
struct drm_connector *physical_connector = bmc_connector->physical_connector;
1776+
1777+
/*
1778+
* Most user-space compositors cannot handle more than one connected
1779+
* connector per CRTC. Hence, we only mark the BMC as connected if the
1780+
* physical connector is disconnected. If the physical connector's status
1781+
* is connected or unknown, the BMC remains disconnected. This has no
1782+
* effect on the output of the BMC.
1783+
*
1784+
* FIXME: Remove this logic once user-space compositors can handle more
1785+
* than one connector per CRTC. The BMC should always be connected.
1786+
*/
1787+
1788+
if (physical_connector && physical_connector->status == connector_status_disconnected)
1789+
return connector_status_connected;
1790+
1791+
return connector_status_disconnected;
1792+
}
1793+
17701794
static int ast_bmc_connector_helper_get_modes(struct drm_connector *connector)
17711795
{
17721796
return drm_add_modes_noedid(connector, 4096, 4096);
17731797
}
17741798

17751799
static const struct drm_connector_helper_funcs ast_bmc_connector_helper_funcs = {
17761800
.get_modes = ast_bmc_connector_helper_get_modes,
1801+
.detect_ctx = ast_bmc_connector_helper_detect_ctx,
17771802
};
17781803

17791804
static const struct drm_connector_funcs ast_bmc_connector_funcs = {
@@ -1784,12 +1809,33 @@ static const struct drm_connector_funcs ast_bmc_connector_funcs = {
17841809
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
17851810
};
17861811

1787-
static int ast_bmc_output_init(struct ast_device *ast)
1812+
static int ast_bmc_connector_init(struct drm_device *dev,
1813+
struct ast_bmc_connector *bmc_connector,
1814+
struct drm_connector *physical_connector)
1815+
{
1816+
struct drm_connector *connector = &bmc_connector->base;
1817+
int ret;
1818+
1819+
ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
1820+
DRM_MODE_CONNECTOR_VIRTUAL);
1821+
if (ret)
1822+
return ret;
1823+
1824+
drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
1825+
1826+
bmc_connector->physical_connector = physical_connector;
1827+
1828+
return 0;
1829+
}
1830+
1831+
static int ast_bmc_output_init(struct ast_device *ast,
1832+
struct drm_connector *physical_connector)
17881833
{
17891834
struct drm_device *dev = &ast->base;
17901835
struct drm_crtc *crtc = &ast->crtc;
17911836
struct drm_encoder *encoder = &ast->output.bmc.encoder;
1792-
struct drm_connector *connector = &ast->output.bmc.connector;
1837+
struct ast_bmc_connector *bmc_connector = &ast->output.bmc.bmc_connector;
1838+
struct drm_connector *connector = &bmc_connector->base;
17931839
int ret;
17941840

17951841
ret = drm_encoder_init(dev, encoder,
@@ -1799,13 +1845,10 @@ static int ast_bmc_output_init(struct ast_device *ast)
17991845
return ret;
18001846
encoder->possible_crtcs = drm_crtc_mask(crtc);
18011847

1802-
ret = drm_connector_init(dev, connector, &ast_bmc_connector_funcs,
1803-
DRM_MODE_CONNECTOR_VIRTUAL);
1848+
ret = ast_bmc_connector_init(dev, bmc_connector, physical_connector);
18041849
if (ret)
18051850
return ret;
18061851

1807-
drm_connector_helper_add(connector, &ast_bmc_connector_helper_funcs);
1808-
18091852
ret = drm_connector_attach_encoder(connector, encoder);
18101853
if (ret)
18111854
return ret;
@@ -1864,6 +1907,7 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = {
18641907
int ast_mode_config_init(struct ast_device *ast)
18651908
{
18661909
struct drm_device *dev = &ast->base;
1910+
struct drm_connector *physical_connector = NULL;
18671911
int ret;
18681912

18691913
ret = drmm_mode_config_init(dev);
@@ -1904,23 +1948,27 @@ int ast_mode_config_init(struct ast_device *ast)
19041948
ret = ast_vga_output_init(ast);
19051949
if (ret)
19061950
return ret;
1951+
physical_connector = &ast->output.vga.vga_connector.base;
19071952
}
19081953
if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
19091954
ret = ast_sil164_output_init(ast);
19101955
if (ret)
19111956
return ret;
1957+
physical_connector = &ast->output.sil164.sil164_connector.base;
19121958
}
19131959
if (ast->tx_chip_types & AST_TX_DP501_BIT) {
19141960
ret = ast_dp501_output_init(ast);
19151961
if (ret)
19161962
return ret;
1963+
physical_connector = &ast->output.dp501.connector;
19171964
}
19181965
if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
19191966
ret = ast_astdp_output_init(ast);
19201967
if (ret)
19211968
return ret;
1969+
physical_connector = &ast->output.astdp.connector;
19221970
}
1923-
ret = ast_bmc_output_init(ast);
1971+
ret = ast_bmc_output_init(ast, physical_connector);
19241972
if (ret)
19251973
return ret;
19261974

0 commit comments

Comments
 (0)