Add helpers for DP501-based connectors. DP501 provides output via DisplayPort. This used to be handled by the VGA connector code. If a DP501 chip has been detected, ast will now create a DisplayPort connector instead of a VGA connector. Remove the DP501 code from ast_vga_connector_helper_get_modes(). Also remove the call to drm_connector_update_edid_property(), which is performed by drm_get_edid(). Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/gpu/drm/ast/ast_drv.h | 4 ++ drivers/gpu/drm/ast/ast_mode.c | 128 +++++++++++++++++++++++++++------ 2 files changed, 109 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index cda50fb887ed..420d19d8459e 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -165,6 +165,10 @@ struct ast_private { struct drm_encoder encoder; struct ast_vga_connector vga_connector; } vga; + struct { + struct drm_encoder encoder; + struct drm_connector connector; + } dp501; } output; bool support_wide_screen; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 17e4e038a3ed..a0f4f042141e 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -40,6 +40,7 @@ #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_vram_helper.h> +#include <drm/drm_managed.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> @@ -1256,30 +1257,22 @@ static int ast_crtc_init(struct drm_device *dev) static int ast_vga_connector_helper_get_modes(struct drm_connector *connector) { struct ast_vga_connector *ast_vga_connector = to_ast_vga_connector(connector); - struct ast_private *ast = to_ast_private(connector->dev); - struct edid *edid = NULL; - bool flags = false; - int ret; + struct edid *edid; + int count; - if (ast->tx_chip_type == AST_TX_DP501) { - edid = kmalloc(128, GFP_KERNEL); - if (!edid) - return -ENOMEM; + if (!ast_vga_connector->i2c) + goto err_drm_connector_update_edid_property; - flags = ast_dp501_read_edid(connector->dev, (u8 *)edid); - if (!flags) { - kfree(edid); - edid = NULL; - } - } - if (!flags && ast_vga_connector->i2c) - edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter); - if (edid) { - drm_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - kfree(edid); - return ret; - } + edid = drm_get_edid(connector, &ast_vga_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; } @@ -1351,6 +1344,92 @@ static int ast_vga_output_init(struct ast_private *ast) return 0; } +/* + * DP501 Connector + */ + +static int ast_dp501_connector_helper_get_modes(struct drm_connector *connector) +{ + void *edid; + bool succ; + int count; + + edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + if (!edid) + goto err_drm_connector_update_edid_property; + + succ = ast_dp501_read_edid(connector->dev, edid); + if (!succ) + goto err_kfree; + + drm_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + kfree(edid); + + return count; + +err_kfree: + kfree(edid); +err_drm_connector_update_edid_property: + drm_connector_update_edid_property(connector, NULL); + return 0; +} + +static const struct drm_connector_helper_funcs ast_dp501_connector_helper_funcs = { + .get_modes = ast_dp501_connector_helper_get_modes, +}; + +static const struct drm_connector_funcs ast_dp501_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_dp501_connector_init(struct drm_device *dev, struct drm_connector *connector) +{ + int ret; + + ret = drm_connector_init(dev, connector, &ast_dp501_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + if (ret) + return ret; + + drm_connector_helper_add(connector, &ast_dp501_connector_helper_funcs); + + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + connector->polled = DRM_CONNECTOR_POLL_CONNECT; + + return 0; +} + +static int ast_dp501_output_init(struct ast_private *ast) +{ + struct drm_device *dev = &ast->base; + struct drm_crtc *crtc = &ast->crtc; + struct drm_encoder *encoder = &ast->output.dp501.encoder; + struct drm_connector *connector = &ast->output.dp501.connector; + 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_dp501_connector_init(dev, connector); + if (ret) + return ret; + + ret = drm_connector_attach_encoder(connector, encoder); + if (ret) + return ret; + + return 0; +} + /* * Mode config */ @@ -1411,10 +1490,13 @@ int ast_mode_config_init(struct ast_private *ast) switch (ast->tx_chip_type) { case AST_TX_NONE: case AST_TX_SIL164: - case AST_TX_DP501: ret = ast_vga_output_init(ast); break; + case AST_TX_DP501: + ret = ast_dp501_output_init(ast); + break; } + if (ret) return ret; -- 2.34.1