drm/ast: Support multiple outputs
authorThomas Zimmermann <tzimmermann@suse.de>
Tue, 7 Jun 2022 09:20:04 +0000 (11:20 +0200)
committerThomas Zimmermann <tzimmermann@suse.de>
Wed, 8 Jun 2022 11:16:15 +0000 (13:16 +0200)
Systems with AST graphics can have multiple output; typically VGA
plus some other port. Record detected output chips in a bitmask and
initialize each output on its own.

Assume a VGA output by default and use SIL164 and DP501 if available.
For ASTDP assume that it can run in parallel with VGA.

Tested on AST2100.

v3:
* define a macro for each BIT(ast_tx_chip) (Patrik)
v2:
* make VGA/SIL164/DP501 mutually exclusive

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Fixes: a59b026419f3 ("drm/ast: Initialize encoder and connector for VGA in helper function")
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: dri-devel@lists.freedesktop.org
Link: https://patchwork.freedesktop.org/patch/msgid/20220607092008.22123-2-tzimmermann@suse.de
drivers/gpu/drm/ast/ast_dp.c
drivers/gpu/drm/ast/ast_dp501.c
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_post.c

index 4551bc8..f573d58 100644 (file)
@@ -160,13 +160,12 @@ void ast_dp_launch(struct drm_device *dev, u8 bPower)
                }
 
                if (bDPExecute)
-                       ast->tx_chip_type = AST_TX_ASTDP;
+                       ast->tx_chip_types |= BIT(AST_TX_ASTDP);
 
                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xE5,
                                                        (u8) ~ASTDP_HOST_EDID_READ_DONE_MASK,
                                                        ASTDP_HOST_EDID_READ_DONE);
-       } else
-               ast->tx_chip_type = AST_TX_NONE;
+       }
 }
 
 
index 204c926..4f75a9e 100644 (file)
@@ -450,7 +450,7 @@ void ast_init_3rdtx(struct drm_device *dev)
                        ast_init_dvo(dev);
                        break;
                default:
-                       if (ast->tx_chip_type == AST_TX_SIL164)
+                       if (ast->tx_chip_types & BIT(AST_TX_SIL164))
                                ast_init_dvo(dev);
                        else
                                ast_init_analog(dev);
index afebe35..a34db43 100644 (file)
@@ -73,6 +73,11 @@ enum ast_tx_chip {
        AST_TX_ASTDP,
 };
 
+#define AST_TX_NONE_BIT                BIT(AST_TX_NONE)
+#define AST_TX_SIL164_BIT      BIT(AST_TX_SIL164)
+#define AST_TX_DP501_BIT       BIT(AST_TX_DP501)
+#define AST_TX_ASTDP_BIT       BIT(AST_TX_ASTDP)
+
 #define AST_DRAM_512Mx16 0
 #define AST_DRAM_1Gx16   1
 #define AST_DRAM_512Mx32 2
@@ -173,7 +178,7 @@ struct ast_private {
        struct drm_plane primary_plane;
        struct ast_cursor_plane cursor_plane;
        struct drm_crtc crtc;
-       union {
+       struct {
                struct {
                        struct drm_encoder encoder;
                        struct ast_vga_connector vga_connector;
@@ -199,7 +204,7 @@ struct ast_private {
                ast_use_defaults
        } config_mode;
 
-       enum ast_tx_chip tx_chip_type;
+       unsigned long tx_chip_types;            /* bitfield of enum ast_chip_type */
        u8 *dp501_fw_addr;
        const struct firmware *dp501_fw;        /* dp501 fw */
 };
index d770d5a..0674532 100644 (file)
@@ -216,7 +216,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
        }
 
        /* Check 3rd Tx option (digital output afaik) */
-       ast->tx_chip_type = AST_TX_NONE;
+       ast->tx_chip_types |= AST_TX_NONE_BIT;
 
        /*
         * VGACRA3 Enhanced Color Mode Register, check if DVO is already
@@ -229,7 +229,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
        if (!*need_post) {
                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xff);
                if (jreg & 0x80)
-                       ast->tx_chip_type = AST_TX_SIL164;
+                       ast->tx_chip_types = AST_TX_SIL164_BIT;
        }
 
        if ((ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST2500)) {
@@ -241,7 +241,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
                jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
                switch (jreg) {
                case 0x04:
-                       ast->tx_chip_type = AST_TX_SIL164;
+                       ast->tx_chip_types = AST_TX_SIL164_BIT;
                        break;
                case 0x08:
                        ast->dp501_fw_addr = drmm_kzalloc(dev, 32*1024, GFP_KERNEL);
@@ -254,22 +254,19 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
                        }
                        fallthrough;
                case 0x0c:
-                       ast->tx_chip_type = AST_TX_DP501;
+                       ast->tx_chip_types = AST_TX_DP501_BIT;
                }
        } else if (ast->chip == AST2600)
                ast_dp_launch(&ast->base, 0);
 
        /* Print stuff for diagnostic purposes */
-       switch(ast->tx_chip_type) {
-       case AST_TX_SIL164:
+       if (ast->tx_chip_types & AST_TX_NONE_BIT)
+               drm_info(dev, "Using analog VGA\n");
+       if (ast->tx_chip_types & AST_TX_SIL164_BIT)
                drm_info(dev, "Using Sil164 TMDS transmitter\n");
-               break;
-       case AST_TX_DP501:
+       if (ast->tx_chip_types & AST_TX_DP501_BIT)
                drm_info(dev, "Using DP501 DisplayPort transmitter\n");
-               break;
-       default:
-               drm_info(dev, "Analog VGA only\n");
-       }
+
        return 0;
 }
 
index 323af27..db2010a 100644 (file)
@@ -997,10 +997,10 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_ON:
                ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0);
                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, 0);
-               if (ast->tx_chip_type == AST_TX_DP501)
+               if (ast->tx_chip_types & AST_TX_DP501_BIT)
                        ast_set_dp501_video_output(crtc->dev, 1);
 
-               if (ast->tx_chip_type == AST_TX_ASTDP) {
+               if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
                        ast_dp_power_on_off(crtc->dev, AST_DP_POWER_ON);
                        ast_wait_for_vretrace(ast);
                        ast_dp_set_on_off(crtc->dev, 1);
@@ -1012,17 +1012,17 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                ch = mode;
-               if (ast->tx_chip_type == AST_TX_DP501)
+               if (ast->tx_chip_types & AST_TX_DP501_BIT)
                        ast_set_dp501_video_output(crtc->dev, 0);
-               break;
 
-               if (ast->tx_chip_type == AST_TX_ASTDP) {
+               if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
                        ast_dp_set_on_off(crtc->dev, 0);
                        ast_dp_power_on_off(crtc->dev, AST_DP_POWER_OFF);
                }
 
                ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT,  0x01, 0xdf, 0x20);
                ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xfc, ch);
+               break;
        }
 }
 
@@ -1155,7 +1155,7 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
                ast_crtc_load_lut(ast, crtc);
 
        //Set Aspeed Display-Port
-       if (ast->tx_chip_type == AST_TX_ASTDP)
+       if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
                ast_dp_set_mode(crtc, vbios_mode_info);
 
        mutex_unlock(&ast->ioregs_lock);
@@ -1739,22 +1739,26 @@ int ast_mode_config_init(struct ast_private *ast)
 
        ast_crtc_init(dev);
 
-       switch (ast->tx_chip_type) {
-       case AST_TX_NONE:
+       if (ast->tx_chip_types & AST_TX_NONE_BIT) {
                ret = ast_vga_output_init(ast);
-               break;
-       case AST_TX_SIL164:
+               if (ret)
+                       return ret;
+       }
+       if (ast->tx_chip_types & AST_TX_SIL164_BIT) {
                ret = ast_sil164_output_init(ast);
-               break;
-       case AST_TX_DP501:
+               if (ret)
+                       return ret;
+       }
+       if (ast->tx_chip_types & AST_TX_DP501_BIT) {
                ret = ast_dp501_output_init(ast);
-               break;
-       case AST_TX_ASTDP:
+               if (ret)
+                       return ret;
+       }
+       if (ast->tx_chip_types & AST_TX_ASTDP_BIT) {
                ret = ast_astdp_output_init(ast);
-               break;
+               if (ret)
+                       return ret;
        }
-       if (ret)
-               return ret;
 
        drm_mode_config_reset(dev);
 
index 0aa9cf0..82fd3c8 100644 (file)
@@ -391,7 +391,7 @@ void ast_post_gpu(struct drm_device *dev)
 
                ast_init_3rdtx(dev);
        } else {
-               if (ast->tx_chip_type != AST_TX_NONE)
+               if (ast->tx_chip_types & AST_TX_SIL164_BIT)
                        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80);        /* Enable DVO */
        }
 }