drm/ast: Base support for AST2500
authorY.C. Chen <yc_chen@aspeedtech.com>
Fri, 17 Feb 2017 03:36:46 +0000 (14:36 +1100)
committerDave Airlie <airlied@redhat.com>
Tue, 28 Feb 2017 03:15:14 +0000 (13:15 +1000)
Add detection and mode setting updates for AST2500 generation chip,
code originally from Aspeed and slightly reworked for coding style
mostly by Ben. This doesn't contain the BMC DRAM POST code which
is in a separate patch.

Signed-off-by: Y.C. Chen <yc_chen@aspeedtech.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Dave Airlie <airlied@redhat.com>
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_tables.h

index 8fcd55c0e63db63df93f3e3ee67ac569942c64a3..8880f0b62e9c2832845d7df2f40e0e77817a9f91 100644 (file)
@@ -65,6 +65,7 @@ enum ast_chip {
        AST2150,
        AST2300,
        AST2400,
+       AST2500,
        AST1180,
 };
 
@@ -81,6 +82,7 @@ enum ast_tx_chip {
 #define AST_DRAM_1Gx32   3
 #define AST_DRAM_2Gx16   6
 #define AST_DRAM_4Gx16   7
+#define AST_DRAM_8Gx16   8
 
 struct ast_fbdev;
 
index fd167008be318251fa9414b0ee27e8d4686193fd..8e8c0310245f8507b388b1aa53e642b773245c11 100644 (file)
@@ -142,7 +142,10 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
                ast->chip = AST1100;
                DRM_INFO("AST 1180 detected\n");
        } else {
-               if (dev->pdev->revision >= 0x30) {
+               if (dev->pdev->revision >= 0x40) {
+                       ast->chip = AST2500;
+                       DRM_INFO("AST 2500 detected\n");
+               } else if (dev->pdev->revision >= 0x30) {
                        ast->chip = AST2400;
                        DRM_INFO("AST 2400 detected\n");
                } else if (dev->pdev->revision >= 0x20) {
@@ -196,6 +199,9 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
                        if (ast->chip == AST2400 &&
                            (scu_rev & 0x300) == 0x100) /* ast1400 */
                                ast->support_wide_screen = true;
+                       if (ast->chip == AST2500 &&
+                           scu_rev == 0x100)           /* ast2510 */
+                               ast->support_wide_screen = true;
                }
                break;
        }
@@ -291,7 +297,10 @@ static int ast_get_dram_info(struct drm_device *dev)
        default:
                ast->dram_bus_width = 16;
                ast->dram_type = AST_DRAM_1Gx16;
-               ast->mclk = 396;
+               if (ast->chip == AST2500)
+                       ast->mclk = 800;
+               else
+                       ast->mclk = 396;
                return 0;
        }
 
@@ -300,7 +309,23 @@ static int ast_get_dram_info(struct drm_device *dev)
        else
                ast->dram_bus_width = 32;
 
-       if (ast->chip == AST2300 || ast->chip == AST2400) {
+       if (ast->chip == AST2500) {
+               switch (mcr_cfg & 0x03) {
+               case 0:
+                       ast->dram_type = AST_DRAM_1Gx16;
+                       break;
+               default:
+               case 1:
+                       ast->dram_type = AST_DRAM_2Gx16;
+                       break;
+               case 2:
+                       ast->dram_type = AST_DRAM_4Gx16;
+                       break;
+               case 3:
+                       ast->dram_type = AST_DRAM_8Gx16;
+                       break;
+               }
+       } else if (ast->chip == AST2300 || ast->chip == AST2400) {
                switch (mcr_cfg & 0x03) {
                case 0:
                        ast->dram_type = AST_DRAM_512Mx16;
@@ -523,6 +548,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
            ast->chip == AST2200 ||
            ast->chip == AST2300 ||
            ast->chip == AST2400 ||
+           ast->chip == AST2500 ||
            ast->chip == AST1180) {
                dev->mode_config.max_width = 1920;
                dev->mode_config.max_height = 2048;
index c25b8b06d55a49d4d86fe34be24ce97c1283f946..47b78e52691cb33bb7cc3b189d92f35b11510340 100644 (file)
@@ -273,7 +273,11 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod
 {
        struct ast_private *ast = crtc->dev->dev_private;
        u8 jreg05 = 0, jreg07 = 0, jreg09 = 0, jregAC = 0, jregAD = 0, jregAE = 0;
-       u16 temp;
+       u16 temp, precache = 0;
+
+       if ((ast->chip == AST2500) &&
+           (vbios_mode->enh_table->flags & AST2500PreCatchCRT))
+               precache = 40;
 
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x00);
 
@@ -299,12 +303,12 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod
                jregAD |= 0x01;  /* HBE D[5] */
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x03, 0xE0, (temp & 0x1f));
 
-       temp = (mode->crtc_hsync_start >> 3) - 1;
+       temp = ((mode->crtc_hsync_start-precache) >> 3) - 1;
        if (temp & 0x100)
                jregAC |= 0x40; /* HRS D[5] */
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x04, 0x00, temp);
 
-       temp = ((mode->crtc_hsync_end >> 3) - 1) & 0x3f;
+       temp = (((mode->crtc_hsync_end-precache) >> 3) - 1) & 0x3f;
        if (temp & 0x20)
                jregAD |= 0x04; /* HRE D[5] */
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x05, 0x60, (u8)((temp & 0x1f) | jreg05));
@@ -365,6 +369,11 @@ static void ast_set_crtc_reg(struct drm_crtc *crtc, struct drm_display_mode *mod
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x09, 0xdf, jreg09);
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xAE, 0x00, (jregAE | 0x80));
 
+       if (precache)
+               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x80);
+       else
+               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0x3f, 0x00);
+
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x11, 0x7f, 0x80);
 }
 
@@ -386,12 +395,16 @@ static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo
        struct ast_private *ast = dev->dev_private;
        const struct ast_vbios_dclk_info *clk_info;
 
-       clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
+       if (ast->chip == AST2500)
+               clk_info = &dclk_table_ast2500[vbios_mode->enh_table->dclk_index];
+       else
+               clk_info = &dclk_table[vbios_mode->enh_table->dclk_index];
 
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc0, 0x00, clk_info->param1);
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xc1, 0x00, clk_info->param2);
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xbb, 0x0f,
-                              (clk_info->param3 & 0x80) | ((clk_info->param3 & 0x3) << 4));
+                              (clk_info->param3 & 0xc0) |
+                              ((clk_info->param3 & 0x3) << 4));
 }
 
 static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode,
@@ -425,7 +438,8 @@ static void ast_set_ext_reg(struct drm_crtc *crtc, struct drm_display_mode *mode
        ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa8, 0xfd, jregA8);
 
        /* Set Threshold */
-       if (ast->chip == AST2300 || ast->chip == AST2400) {
+       if (ast->chip == AST2300 || ast->chip == AST2400 ||
+           ast->chip == AST2500) {
                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
                ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
        } else if (ast->chip == AST2100 ||
@@ -800,7 +814,9 @@ static int ast_mode_valid(struct drm_connector *connector,
                if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
                        return MODE_OK;
 
-               if ((ast->chip == AST2100) || (ast->chip == AST2200) || (ast->chip == AST2300) || (ast->chip == AST2400) || (ast->chip == AST1180)) {
+               if ((ast->chip == AST2100) || (ast->chip == AST2200) ||
+                   (ast->chip == AST2300) || (ast->chip == AST2400) ||
+                   (ast->chip == AST2500) || (ast->chip == AST1180)) {
                        if ((mode->hdisplay == 1920) && (mode->vdisplay == 1080))
                                return MODE_OK;
 
index a4ddf901a54febc74f47a7808cb8da9854130ed2..5f4c2e833a650dd6be2e6afb5e9835cf7e434e17 100644 (file)
@@ -47,6 +47,7 @@
 #define SyncPN                 (PVSync | NHSync)
 #define SyncNP                 (NVSync | PHSync)
 #define SyncNN                 (NVSync | NHSync)
+#define AST2500PreCatchCRT             0x00004000
 
 /* DCLK Index */
 #define VCLK25_175                     0x00
@@ -108,6 +109,36 @@ static const struct ast_vbios_dclk_info dclk_table[] = {
        {0x3b, 0x2c, 0x81},                     /* 1A: VCLK118_25       */
 };
 
+static const struct ast_vbios_dclk_info dclk_table_ast2500[] = {
+       {0x2C, 0xE7, 0x03},                     /* 00: VCLK25_175       */
+       {0x95, 0x62, 0x03},                     /* 01: VCLK28_322       */
+       {0x67, 0x63, 0x01},                     /* 02: VCLK31_5         */
+       {0x76, 0x63, 0x01},                     /* 03: VCLK36           */
+       {0xEE, 0x67, 0x01},                     /* 04: VCLK40           */
+       {0x82, 0x62, 0x01},                     /* 05: VCLK49_5         */
+       {0xC6, 0x64, 0x01},                     /* 06: VCLK50           */
+       {0x94, 0x62, 0x01},                     /* 07: VCLK56_25        */
+       {0x80, 0x64, 0x00},                     /* 08: VCLK65           */
+       {0x7B, 0x63, 0x00},                     /* 09: VCLK75           */
+       {0x67, 0x62, 0x00},                     /* 0A: VCLK78_75        */
+       {0x7C, 0x62, 0x00},                     /* 0B: VCLK94_5         */
+       {0x8E, 0x62, 0x00},                     /* 0C: VCLK108          */
+       {0x85, 0x24, 0x00},                     /* 0D: VCLK135          */
+       {0x67, 0x22, 0x00},                     /* 0E: VCLK157_5        */
+       {0x6A, 0x22, 0x00},                     /* 0F: VCLK162          */
+       {0x4d, 0x4c, 0x80},                     /* 10: VCLK154          */
+       {0xa7, 0x78, 0x80},                     /* 11: VCLK83.5         */
+       {0x28, 0x49, 0x80},                     /* 12: VCLK106.5        */
+       {0x37, 0x49, 0x80},                     /* 13: VCLK146.25       */
+       {0x1f, 0x45, 0x80},                     /* 14: VCLK148.5        */
+       {0x47, 0x6c, 0x80},                     /* 15: VCLK71           */
+       {0x25, 0x65, 0x80},                     /* 16: VCLK88.75        */
+       {0x58, 0x01, 0x42},                     /* 17: VCLK119          */
+       {0x32, 0x67, 0x80},                     /* 18: VCLK85_5         */
+       {0x6a, 0x6d, 0x80},                     /* 19: VCLK97_75        */
+       {0x44, 0x20, 0x43},                     /* 1A: VCLK118_25       */
+};
+
 static const struct ast_vbios_stdtable vbios_stdtable[] = {
        /* MD_2_3_400 */
        {
@@ -246,12 +277,14 @@ static const struct ast_vbios_enhtable res_1360x768[] = {
        {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5,         /* 60Hz */
         (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 },
        {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5,          /* end */
-        (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 },
+        (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 0xFF, 1, 0x39 },
 };
 
 static const struct ast_vbios_enhtable res_1600x900[] = {
        {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75,         /* 60Hz CVT RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x3A },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x3A },
        {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25,       /* 60Hz CVT */
         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A },
        {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25,       /* 60Hz CVT */
@@ -260,16 +293,19 @@ static const struct ast_vbios_enhtable res_1600x900[] = {
 
 static const struct ast_vbios_enhtable res_1920x1080[] = {
        {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x38 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x38 },
        {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x38 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 0xFF, 1, 0x38 },
 };
 
 
 /* 16:10 */
 static const struct ast_vbios_enhtable res_1280x800[] = {
        {1440, 1280, 48, 32,  823,  800, 3, 6, VCLK71,          /* 60Hz RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x35 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x35 },
        {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 },
        {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
@@ -279,7 +315,8 @@ static const struct ast_vbios_enhtable res_1280x800[] = {
 
 static const struct ast_vbios_enhtable res_1440x900[] = {
        {1600, 1440, 48, 32,  926,  900, 3, 6, VCLK88_75,       /* 60Hz RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x36 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x36 },
        {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 },
        {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
@@ -288,7 +325,8 @@ static const struct ast_vbios_enhtable res_1440x900[] = {
 
 static const struct ast_vbios_enhtable res_1680x1050[] = {
        {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119,         /* 60Hz RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x37 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x37 },
        {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25,      /* 60Hz */
         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 },
        {2240, 1680,104,176, 1089, 1050, 3, 6, VCLK146_25,      /* 60Hz */
@@ -297,9 +335,11 @@ static const struct ast_vbios_enhtable res_1680x1050[] = {
 
 static const struct ast_vbios_enhtable res_1920x1200[] = {
        {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154,         /* 60Hz RB*/
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x34 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x34 },
        {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154,         /* 60Hz RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x34 },
+        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 0xFF, 1, 0x34 },
 };
 
 #endif