drm/ast: Move DP501-based connector code into separate helpers
authorThomas Zimmermann <tzimmermann@suse.de>
Mon, 7 Feb 2022 14:15:43 +0000 (15:15 +0100)
committerThomas Zimmermann <tzimmermann@suse.de>
Tue, 8 Feb 2022 12:40:18 +0000 (13:40 +0100)
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@suse.de>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220207141544.30015-9-tzimmermann@suse.de
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_mode.c

index cda50fb..420d19d 100644 (file)
@@ -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;
index 09995a3..12dbf5b 100644 (file)
@@ -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>
@@ -1259,30 +1260,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;
 }
@@ -1355,6 +1348,92 @@ static int ast_vga_output_init(struct ast_private *ast)
 }
 
 /*
+ * 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
  */
 
@@ -1414,10 +1493,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;