diff options
author | Thomas Zimmermann <tzimmermann@suse.de> | 2022-02-07 17:15:44 +0300 |
---|---|---|
committer | Thomas Zimmermann <tzimmermann@suse.de> | 2022-02-08 15:40:18 +0300 |
commit | 5e78d59a1ead969669f64dde4245cfa65b7cc4a9 (patch) | |
tree | 22fc8ece37852936e7e7387e6c7c2961ebfaa27a /drivers/gpu/drm/ast | |
parent | 3ab26eddc67a67579a2b52f908b69cbc253f5ff3 (diff) | |
download | linux-5e78d59a1ead969669f64dde4245cfa65b7cc4a9.tar.xz |
drm/ast: Move SIL164-based connector code into separate helpers
Add helpers for initializing SIL164-based connectors. These used to be
handled by the VGA connector code. But SIL164 provides output via DVI-I,
so set the encoder and connector types accordingly.
If a SIL164 chip has been detected, ast will now create a DVI-I
connector instead of a VGA connector.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220207141544.30015-10-tzimmermann@suse.de
Diffstat (limited to 'drivers/gpu/drm/ast')
-rw-r--r-- | drivers/gpu/drm/ast/ast_drv.h | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/ast/ast_mode.c | 99 |
2 files changed, 112 insertions, 2 deletions
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 420d19d8459e..c3a582372649 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -140,6 +140,17 @@ to_ast_vga_connector(struct drm_connector *connector) return container_of(connector, struct ast_vga_connector, base); } +struct ast_sil164_connector { + struct drm_connector base; + struct ast_i2c_chan *i2c; +}; + +static inline struct ast_sil164_connector * +to_ast_sil164_connector(struct drm_connector *connector) +{ + return container_of(connector, struct ast_sil164_connector, base); +} + /* * Device */ @@ -167,6 +178,10 @@ struct ast_private { } vga; struct { struct drm_encoder encoder; + struct ast_sil164_connector sil164_connector; + } sil164; + struct { + struct drm_encoder encoder; struct drm_connector connector; } dp501; } output; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 12dbf5b229e6..6f4aa8e8b0ab 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -1348,6 +1348,100 @@ static int ast_vga_output_init(struct ast_private *ast) } /* + * SIL164 Connector + */ + +static int ast_sil164_connector_helper_get_modes(struct drm_connector *connector) +{ + struct ast_sil164_connector *ast_sil164_connector = to_ast_sil164_connector(connector); + struct edid *edid; + int count; + + if (!ast_sil164_connector->i2c) + goto err_drm_connector_update_edid_property; + + edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter); + if (!edid) + goto err_drm_connector_update_edid_property; + + count = drm_add_edid_modes(connector, edid); + kfree(edid); + + return count; + +err_drm_connector_update_edid_property: + drm_connector_update_edid_property(connector, NULL); + return 0; +} + +static const struct drm_connector_helper_funcs ast_sil164_connector_helper_funcs = { + .get_modes = ast_sil164_connector_helper_get_modes, +}; + +static const struct drm_connector_funcs ast_sil164_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int ast_sil164_connector_init(struct drm_device *dev, + struct ast_sil164_connector *ast_sil164_connector) +{ + struct drm_connector *connector = &ast_sil164_connector->base; + int ret; + + ast_sil164_connector->i2c = ast_i2c_create(dev); + if (!ast_sil164_connector->i2c) + drm_err(dev, "failed to add ddc bus for connector\n"); + + if (ast_sil164_connector->i2c) + ret = drm_connector_init_with_ddc(dev, connector, &ast_sil164_connector_funcs, + DRM_MODE_CONNECTOR_DVII, + &ast_sil164_connector->i2c->adapter); + else + ret = drm_connector_init(dev, connector, &ast_sil164_connector_funcs, + DRM_MODE_CONNECTOR_DVII); + if (ret) + return ret; + + drm_connector_helper_add(connector, &ast_sil164_connector_helper_funcs); + + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + + return 0; +} + +static int ast_sil164_output_init(struct ast_private *ast) +{ + struct drm_device *dev = &ast->base; + struct drm_crtc *crtc = &ast->crtc; + struct drm_encoder *encoder = &ast->output.sil164.encoder; + struct ast_sil164_connector *ast_sil164_connector = &ast->output.sil164.sil164_connector; + struct drm_connector *connector = &ast_sil164_connector->base; + int ret; + + ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS); + if (ret) + return ret; + encoder->possible_crtcs = drm_crtc_mask(crtc); + + ret = ast_sil164_connector_init(dev, ast_sil164_connector); + if (ret) + return ret; + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) + return ret; + + return 0; +} + +/* * DP501 Connector */ @@ -1492,14 +1586,15 @@ int ast_mode_config_init(struct ast_private *ast) switch (ast->tx_chip_type) { case AST_TX_NONE: - case AST_TX_SIL164: ret = ast_vga_output_init(ast); break; + case AST_TX_SIL164: + ret = ast_sil164_output_init(ast); + break; case AST_TX_DP501: ret = ast_dp501_output_init(ast); break; } - if (ret) return ret; |