diff mbox

drm/ast: Support AST2500

Message ID 1484103473-22931-1-git-send-email-yc_chen@aspeedtech.com (mailing list archive)
State New, archived
Headers show

Commit Message

Y.C. Chen Jan. 11, 2017, 2:57 a.m. UTC
From: "Y.C. Chen" <yc_chen@aspeedtech.com>

Signed-off-by: Y.C. Chen <yc_chen@aspeedtech.com>
---
 drivers/gpu/drm/ast/ast_drv.h    |   2 +
 drivers/gpu/drm/ast/ast_main.c   |  27 ++-
 drivers/gpu/drm/ast/ast_mode.c   |  25 +-
 drivers/gpu/drm/ast/ast_post.c   | 510 ++++++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/ast/ast_tables.h |  57 ++++-
 5 files changed, 596 insertions(+), 25 deletions(-)

Comments

Benjamin Herrenschmidt Feb. 16, 2017, 4:04 a.m. UTC | #1
On Wed, 2017-01-11 at 10:57 +0800, Y.C. Chen wrote:
> From: "Y.C. Chen" <yc_chen@aspeedtech.com>
> 
> Signed-off-by: Y.C. Chen <yc_chen@aspeedtech.com>
> ---
>  drivers/gpu/drm/ast/ast_drv.h    |   2 +
>  drivers/gpu/drm/ast/ast_main.c   |  27 ++-
>  drivers/gpu/drm/ast/ast_mode.c   |  25 +-
>  drivers/gpu/drm/ast/ast_post.c   | 510
> ++++++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/ast/ast_tables.h |  57 ++++-
>  5 files changed, 596 insertions(+), 25 deletions(-)

Dave, Daniel, is that going upstream ? We need that for POWER9
machines, it needs to hit the distros ASAP.

We also need the one Russell Currey sent a while ago

"[PATCH] drivers/gpu/drm/ast: Support reading configuration values from
device tree"

Cheers,
Ben.
Dave Airlie Feb. 16, 2017, 4:24 a.m. UTC | #2
On 11 January 2017 at 12:57, Y.C. Chen <yc_chen@aspeedtech.com> wrote:
> From: "Y.C. Chen" <yc_chen@aspeedtech.com>

Please run checkpatch over this patch, it's got a lot of bad whitespace issues
(4 space and 2 space indents, indent the timing tables , remove start
of line whitespace.).

Dave.

>
> Signed-off-by: Y.C. Chen <yc_chen@aspeedtech.com>
> ---
>  drivers/gpu/drm/ast/ast_drv.h    |   2 +
>  drivers/gpu/drm/ast/ast_main.c   |  27 ++-
>  drivers/gpu/drm/ast/ast_mode.c   |  25 +-
>  drivers/gpu/drm/ast/ast_post.c   | 510 ++++++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/ast/ast_tables.h |  57 ++++-
>  5 files changed, 596 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
> index 908011d..7e406ce 100644
> --- a/drivers/gpu/drm/ast/ast_drv.h
> +++ b/drivers/gpu/drm/ast/ast_drv.h
> @@ -64,6 +64,7 @@ enum ast_chip {
>         AST2150,
>         AST2300,
>         AST2400,
> +       AST2500,
>         AST1180,
>  };
>
> @@ -80,6 +81,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;
>
> diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
> index f75c642..40460ce 100644
> --- a/drivers/gpu/drm/ast/ast_main.c
> +++ b/drivers/gpu/drm/ast/ast_main.c
> @@ -73,7 +73,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) {
> @@ -149,6 +152,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
>                                 ast->support_wide_screen = true;
>                         if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
>                                 ast->support_wide_screen = true;
> +                       if (ast->chip == AST2500 && data == 0x100) /* ast2510 */
> +                               ast->support_wide_screen = true;
>                 }
>                 break;
>         }
> @@ -233,7 +238,24 @@ 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 (data & 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 (data & 0x03) {
>                 case 0:
>                         ast->dram_type = AST_DRAM_512Mx16;
> @@ -456,6 +478,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;
> diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
> index e26c98f..242ca7f 100644
> --- a/drivers/gpu/drm/ast/ast_mode.c
> +++ b/drivers/gpu/drm/ast/ast_mode.c
> @@ -271,7 +271,10 @@ 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);
>
> @@ -297,12 +300,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));
> @@ -363,6 +366,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);
>  }
>
> @@ -383,12 +391,15 @@ static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo
>         struct ast_private *ast = dev->dev_private;
>         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,
> @@ -421,7 +432,7 @@ 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 ||
> @@ -794,7 +805,7 @@ 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;
>
> diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
> index 810c51d..05d7d36 100644
> --- a/drivers/gpu/drm/ast/ast_post.c
> +++ b/drivers/gpu/drm/ast/ast_post.c
> @@ -32,6 +32,7 @@
>  #include "ast_dram_tables.h"
>
>  static void ast_init_dram_2300(struct drm_device *dev);
> +static void ast_init_dram_2500(struct drm_device *dev);
>
>  void ast_enable_vga(struct drm_device *dev)
>  {
> @@ -82,7 +83,7 @@ bool ast_is_vga_enabled(struct drm_device *dev)
>         for (i = 0x81; i <= 0x8f; i++)
>                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
>
> -       if (ast->chip == AST2300 || ast->chip == AST2400) {
> +       if (ast->chip == AST2300 || ast->chip == AST2400 || ast->chip == AST2500) {
>                 if (dev->pdev->revision >= 0x20)
>                         ext_reg_info = extreginfo_ast2300;
>                 else
> @@ -106,7 +107,7 @@ bool ast_is_vga_enabled(struct drm_device *dev)
>
>         /* Enable RAMDAC for A1 */
>         reg = 0x04;
> -       if (ast->chip == AST2300 || ast->chip == AST2400)
> +       if (ast->chip == AST2300 || ast->chip == AST2400 || ast->chip == AST2500)
>                 reg |= 0x20;
>         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
>  }
> @@ -379,7 +380,9 @@ void ast_post_gpu(struct drm_device *dev)
>         ast_open_key(ast);
>         ast_set_def_ext_reg(dev);
>
> -       if (ast->chip == AST2300 || ast->chip == AST2400)
> +       if (ast->chip == AST2500)
> +               ast_init_dram_2500(dev);
> +       else if (ast->chip == AST2300 || ast->chip == AST2400)
>                 ast_init_dram_2300(dev);
>         else
>                 ast_init_dram_reg(dev);
> @@ -1655,3 +1658,504 @@ static void ast_init_dram_2300(struct drm_device *dev)
>         } while ((reg & 0x40) == 0);
>  }
>
> +/*
> + * AST2500 DRAM settings modules
> + */
> +#define REGTBL_NUM           17
> +#define REGIDX_010           0
> +#define REGIDX_014           1
> +#define REGIDX_018           2
> +#define REGIDX_020           3
> +#define REGIDX_024           4
> +#define REGIDX_02C           5
> +#define REGIDX_030           6
> +#define REGIDX_214           7
> +#define REGIDX_2E0           8
> +#define REGIDX_2E4           9
> +#define REGIDX_2E8           10
> +#define REGIDX_2EC           11
> +#define REGIDX_2F0           12
> +#define REGIDX_2F4           13
> +#define REGIDX_2F8           14
> +#define REGIDX_RFC           15
> +#define REGIDX_PLL           16
> +
> +static u32 ddr3_1600_timing_table[REGTBL_NUM] = {
> +0x64604D38,                  /* 0x010 */
> +0x29690599,                  /* 0x014 */
> +0x00000300,                  /* 0x018 */
> +0x00000000,                  /* 0x020 */
> +0x00000000,                  /* 0x024 */
> +0x02181E70,                  /* 0x02C */
> +0x00000040,                  /* 0x030 */
> +0x00000024,                  /* 0x214 */
> +0x02001300,                  /* 0x2E0 */
> +0x0E0000A0,                  /* 0x2E4 */
> +0x000E001B,                  /* 0x2E8 */
> +0x35B8C105,                  /* 0x2EC */
> +0x08090408,                  /* 0x2F0 */
> +0x9B000800,                  /* 0x2F4 */
> +0x0E400A00,                  /* 0x2F8 */
> +0x9971452F,                  /* tRFC  */
> +0x000071C1};                 /* PLL   */
> +
> +static u32 ddr4_1600_timing_table[REGTBL_NUM] = {
> +0x63604E37,                  /* 0x010 */
> +0xE97AFA99,                  /* 0x014 */
> +0x00019000,                  /* 0x018 */
> +0x08000000,                  /* 0x020 */
> +0x00000400,                  /* 0x024 */
> +0x00000410,                  /* 0x02C */
> +0x00000101,                  /* 0x030 */
> +0x00000024,                  /* 0x214 */
> +0x03002900,                  /* 0x2E0 */
> +0x0E0000A0,                  /* 0x2E4 */
> +0x000E001C,                  /* 0x2E8 */
> +0x35B8C106,                  /* 0x2EC */
> +0x08080607,                  /* 0x2F0 */
> +0x9B000900,                  /* 0x2F4 */
> +0x0E400A00,                  /* 0x2F8 */
> +0x99714545,                  /* tRFC  */
> +0x000071C1};                 /* PLL   */
> +
> +static u32 MMCTestBurst_AST2500(struct ast_private *ast, u32 datagen)
> +{
> +  u32 data, timecnt;
> +
> +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0070, 0x000000C1 | (datagen << 3));
> +  timecnt = 0;
> +  do{
> +    data = ast_mindwm(ast, 0x1E6E0070) & 0x3000;
> +    if(data & 0x2000){
> +      return(0);
> +    }
> +    if(++timecnt > TIMEOUT){
> +      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> +      return(0);
> +    }
> +  }while(!data);
> +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> +  return(1);
> +}
> +
> +static u32 MMCTestSingle_AST2500(struct ast_private *ast, u32 datagen)
> +{
> +  u32 data, timecnt;
> +
> +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0070, 0x00000085 | (datagen << 3));
> +  timecnt = 0;
> +  do{
> +    data = ast_mindwm(ast, 0x1E6E0070) & 0x3000;
> +    if(data & 0x2000){
> +      return(0);
> +    }
> +    if(++timecnt > TIMEOUT){
> +      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> +      return(0);
> +    }
> +  }while(!data);
> +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> +  return(1);
> +}
> +
> +static u32 CBRTest_AST2500(struct ast_private *ast)
> +{
> +  ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
> +  ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
> +  if(!MMCTestBurst_AST2500(ast, 0)) return(0);
> +  if(!MMCTestSingle_AST2500(ast, 0)) return(0);
> +  return(1);
> +}
> +
> +static bool DDRTest_AST2500(struct ast_private *ast)
> +{
> +  ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
> +  ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
> +  if(!MMCTestBurst_AST2500(ast, 0)) return(0);
> +  if(!MMCTestBurst_AST2500(ast, 1)) return(0);
> +  if(!MMCTestBurst_AST2500(ast, 2)) return(0);
> +  if(!MMCTestBurst_AST2500(ast, 3)) return(0);
> +  if(!MMCTestSingle_AST2500(ast, 0)) return(0);
> +  return(1);
> +}
> +
> +static void DDR_Init_Common(struct ast_private *ast)
> +{
> +  ast_moutdwm(ast, 0x1E6E0034,0x00020080);
> +  ast_moutdwm(ast, 0x1E6E0008,0x2003000F);
> +  ast_moutdwm(ast, 0x1E6E0038,0x00000FFF);
> +  ast_moutdwm(ast, 0x1E6E0040,0x88448844);
> +  ast_moutdwm(ast, 0x1E6E0044,0x24422288);
> +  ast_moutdwm(ast, 0x1E6E0048,0x22222222);
> +  ast_moutdwm(ast, 0x1E6E004C,0x22222222);
> +  ast_moutdwm(ast, 0x1E6E0050,0x80000000);
> +  ast_moutdwm(ast, 0x1E6E0208,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0218,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0220,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0228,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0230,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E02A8,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E02B0,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0240,0x86000000);
> +  ast_moutdwm(ast, 0x1E6E0244,0x00008600);
> +  ast_moutdwm(ast, 0x1E6E0248,0x80000000);
> +  ast_moutdwm(ast, 0x1E6E024C,0x80808080);
> +}
> +
> +static void Do_DDRPHY_Init(struct ast_private *ast)
> +{
> +  u32 data, pass, timecnt;
> +
> +  pass = 0;
> +  ast_moutdwm(ast, 0x1E6E0060,0x00000005);
> +  while(!pass){
> +    for(timecnt = 0;timecnt < TIMEOUT;timecnt++){
> +      data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
> +      if(!data){
> +        break;
> +      }
> +    }
> +    if(timecnt != TIMEOUT){
> +      data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
> +      if(!data){
> +        pass = 1;
> +      }
> +    }
> +    if(!pass){
> +      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> +      udelay(10); /* delay 10 us */
> +      ast_moutdwm(ast, 0x1E6E0060,0x00000005);
> +    }
> +  }
> +
> +  ast_moutdwm(ast, 0x1E6E0060,0x00000006);
> +}
> +
> +/******************************************************************************
> + Check DRAM Size
> + 1Gb : 0x80000000 ~ 0x87FFFFFF
> + 2Gb : 0x80000000 ~ 0x8FFFFFFF
> + 4Gb : 0x80000000 ~ 0x9FFFFFFF
> + 8Gb : 0x80000000 ~ 0xBFFFFFFF
> + *****************************************************************************/
> +static void Check_DRAM_Size(struct ast_private *ast, u32 tRFC)
> +{
> +  u32 reg_04, reg_14;
> +
> +  reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
> +  reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
> +
> +  ast_moutdwm(ast, 0xA0100000, 0x41424344);
> +  ast_moutdwm(ast, 0x90100000, 0x35363738);
> +  ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
> +  ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
> +
> +  /* Check 8Gbit */
> +  if(ast_mindwm(ast, 0xA0100000) == 0x41424344){
> +    reg_04 |= 0x03;
> +    reg_14 |= (tRFC >> 24) & 0xFF;
> +  /* Check 4Gbit */
> +  }else if(ast_mindwm(ast, 0x90100000) == 0x35363738){
> +    reg_04 |= 0x02;
> +    reg_14 |= (tRFC >> 16) & 0xFF;
> +  /* Check 2Gbit */
> +  }else if(ast_mindwm(ast, 0x88100000) == 0x292A2B2C){
> +    reg_04 |= 0x01;
> +    reg_14 |= (tRFC >> 8) & 0xFF;
> +  }else{
> +    reg_14 |= tRFC & 0xFF;
> +  }
> +  ast_moutdwm(ast, 0x1E6E0004, reg_04);
> +  ast_moutdwm(ast, 0x1E6E0014, reg_14);
> +}
> +
> +static void Enable_Cache(struct ast_private *ast)
> +{
> +  u32 reg_04, data;
> +
> +  reg_04 = ast_mindwm(ast, 0x1E6E0004);
> +  ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
> +
> +  do{
> +    data = ast_mindwm(ast, 0x1E6E0004);
> +  }while(!(data & 0x80000));
> +  ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
> +}
> +
> +static void Set_MPLL(struct ast_private *ast)
> +{
> +  u32 addr, data, param;
> +
> +  /* Reset MMC */
> +  ast_moutdwm(ast, 0x1E6E0000,0xFC600309);
> +  ast_moutdwm(ast, 0x1E6E0034,0x00020080);
> +  for(addr = 0x1e6e0004;addr < 0x1e6e0090;){
> +    ast_moutdwm(ast, addr, 0x0);
> +    addr += 4;
> +  }
> +  ast_moutdwm(ast, 0x1E6E0034,0x00020000);
> +
> +  ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
> +  data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
> +  if(data){                  /* CLKIN = 25MHz */
> +    param = 0x930023E0;
> +    ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
> +  }else{                                        /* CLKIN = 24MHz */
> +    param = 0x93002400;
> +  }
> +  ast_moutdwm(ast, 0x1E6E2020, param);
> +  udelay(100);
> +}
> +
> +static void Reset_MMC(struct ast_private *ast)
> +{
> +  ast_moutdwm(ast, 0x1E78505C,0x00000004);
> +  ast_moutdwm(ast, 0x1E785044,0x00000001);
> +  ast_moutdwm(ast, 0x1E785048,0x00004755);
> +  ast_moutdwm(ast, 0x1E78504C,0x00000013);
> +  mdelay(100);                                 /* delay 100ms */
> +  ast_moutdwm(ast, 0x1E785054,0x00000077);
> +  ast_moutdwm(ast, 0x1E6E0000,0xFC600309);
> +}
> +
> +static void DDR3_Init_AST2500(struct ast_private *ast, u32 *ddr_table)
> +{
> +
> +  ast_moutdwm(ast, 0x1E6E0004,0x00000303);
> +  ast_moutdwm(ast, 0x1E6E0010,ddr_table[REGIDX_010]);
> +  ast_moutdwm(ast, 0x1E6E0014,ddr_table[REGIDX_014]);
> +  ast_moutdwm(ast, 0x1E6E0018,ddr_table[REGIDX_018]);
> +  ast_moutdwm(ast, 0x1E6E0020,ddr_table[REGIDX_020]);          /* MODEREG4/6 */
> +  ast_moutdwm(ast, 0x1E6E0024,ddr_table[REGIDX_024]);          /* MODEREG5 */
> +  ast_moutdwm(ast, 0x1E6E002C,ddr_table[REGIDX_02C] | 0x100);  /* MODEREG0/2 */
> +  ast_moutdwm(ast, 0x1E6E0030,ddr_table[REGIDX_030]);          /* MODEREG1/3 */
> +
> +  /* DDR PHY Setting */
> +  ast_moutdwm(ast, 0x1E6E0200,0x02492AAE);
> +  ast_moutdwm(ast, 0x1E6E0204,0x00001001);
> +  ast_moutdwm(ast, 0x1E6E020C,0x55E00B0B);
> +  ast_moutdwm(ast, 0x1E6E0210,0x20000000);
> +  ast_moutdwm(ast, 0x1E6E0214,ddr_table[REGIDX_214]);
> +  ast_moutdwm(ast, 0x1E6E02E0,ddr_table[REGIDX_2E0]);
> +  ast_moutdwm(ast, 0x1E6E02E4,ddr_table[REGIDX_2E4]);
> +  ast_moutdwm(ast, 0x1E6E02E8,ddr_table[REGIDX_2E8]);
> +  ast_moutdwm(ast, 0x1E6E02EC,ddr_table[REGIDX_2EC]);
> +  ast_moutdwm(ast, 0x1E6E02F0,ddr_table[REGIDX_2F0]);
> +  ast_moutdwm(ast, 0x1E6E02F4,ddr_table[REGIDX_2F4]);
> +  ast_moutdwm(ast, 0x1E6E02F8,ddr_table[REGIDX_2F8]);
> +  ast_moutdwm(ast, 0x1E6E0290,0x00100008);
> +  ast_moutdwm(ast, 0x1E6E02C0,0x00000006);
> +
> +  /* Controller Setting */
> +  ast_moutdwm(ast, 0x1E6E0034,0x00020091);
> +
> +  /* Wait DDR PHY init done */
> +  Do_DDRPHY_Init(ast);
> +
> +  ast_moutdwm(ast, 0x1E6E0120,ddr_table[REGIDX_PLL]);
> +  ast_moutdwm(ast, 0x1E6E000C,0x42AA5C81);
> +  ast_moutdwm(ast, 0x1E6E0034,0x0001AF93);
> +
> +  Check_DRAM_Size(ast, ddr_table[REGIDX_RFC]);
> +  Enable_Cache(ast);
> +  ast_moutdwm(ast, 0x1E6E001C,0x00000008);
> +  ast_moutdwm(ast, 0x1E6E0038,0xFFFFFF00);
> +}
> +
> +static void DDR4_Init_AST2500(struct ast_private *ast, u32 *ddr_table)
> +{
> +  u32 data, data2, pass, retrycnt;
> +  u32 ddr_vref, phy_vref;
> +  u32 min_ddr_vref=0, min_phy_vref=0;
> +  u32 max_ddr_vref=0, max_phy_vref=0;
> +
> +  ast_moutdwm(ast, 0x1E6E0004,0x00000313);
> +  ast_moutdwm(ast, 0x1E6E0010,ddr_table[REGIDX_010]);
> +  ast_moutdwm(ast, 0x1E6E0014,ddr_table[REGIDX_014]);
> +  ast_moutdwm(ast, 0x1E6E0018,ddr_table[REGIDX_018]);
> +  ast_moutdwm(ast, 0x1E6E0020,ddr_table[REGIDX_020]);          /* MODEREG4/6 */
> +  ast_moutdwm(ast, 0x1E6E0024,ddr_table[REGIDX_024]);          /* MODEREG5 */
> +  ast_moutdwm(ast, 0x1E6E002C,ddr_table[REGIDX_02C] | 0x100);  /* MODEREG0/2 */
> +  ast_moutdwm(ast, 0x1E6E0030,ddr_table[REGIDX_030]);          /* MODEREG1/3 */
> +
> +  /* DDR PHY Setting */
> +  ast_moutdwm(ast, 0x1E6E0200,0x42492AAE);
> +  ast_moutdwm(ast, 0x1E6E0204,0x09002000);
> +  ast_moutdwm(ast, 0x1E6E020C,0x55E00B0B);
> +  ast_moutdwm(ast, 0x1E6E0210,0x20000000);
> +  ast_moutdwm(ast, 0x1E6E0214,ddr_table[REGIDX_214]);
> +  ast_moutdwm(ast, 0x1E6E02E0,ddr_table[REGIDX_2E0]);
> +  ast_moutdwm(ast, 0x1E6E02E4,ddr_table[REGIDX_2E4]);
> +  ast_moutdwm(ast, 0x1E6E02E8,ddr_table[REGIDX_2E8]);
> +  ast_moutdwm(ast, 0x1E6E02EC,ddr_table[REGIDX_2EC]);
> +  ast_moutdwm(ast, 0x1E6E02F0,ddr_table[REGIDX_2F0]);
> +  ast_moutdwm(ast, 0x1E6E02F4,ddr_table[REGIDX_2F4]);
> +  ast_moutdwm(ast, 0x1E6E02F8,ddr_table[REGIDX_2F8]);
> +  ast_moutdwm(ast, 0x1E6E0290,0x00100008);
> +  ast_moutdwm(ast, 0x1E6E02C4,0x3C183C3C);
> +  ast_moutdwm(ast, 0x1E6E02C8,0x00631E0E);
> +
> +  /* Controller Setting */
> +  ast_moutdwm(ast, 0x1E6E0034,0x0001A991);
> +
> +  /* Train PHY Vref first */
> +  pass = 0;                                                                                         /* add at V1.1 */
> +  for(retrycnt = 0;retrycnt < 4 && pass == 0;retrycnt++){                                           /* add at V1.1 */
> +    max_phy_vref = 0x0;
> +    pass = 0;
> +    ast_moutdwm(ast, 0x1E6E02C0,0x00001C06);
> +    for(phy_vref = 0x40;phy_vref < 0x80;phy_vref++){
> +      ast_moutdwm(ast, 0x1E6E000C,0x00000000);
> +      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> +      ast_moutdwm(ast, 0x1E6E02CC,phy_vref | (phy_vref << 8));
> +      /* Fire DFI Init */
> +      Do_DDRPHY_Init(ast);
> +      ast_moutdwm(ast, 0x1E6E000C,0x00005C01);
> +      if(CBRTest_AST2500(ast)){
> +        pass++;
> +        data = ast_mindwm(ast, 0x1E6E03D0);
> +        data2 = data >> 8;
> +        data  = data & 0xff;
> +        if(data > data2){
> +          data = data2;
> +        }
> +
> +        if(max_phy_vref < data){
> +          max_phy_vref = data;
> +          min_phy_vref = phy_vref;
> +        }
> +      }else if(pass > 0){
> +        break;
> +      }
> +    }
> +  }                                                                                                 /* add at V1.1 */
> +  ast_moutdwm(ast, 0x1E6E02CC,min_phy_vref | (min_phy_vref << 8));
> +
> +  /* Train DDR Vref next */
> +  pass = 0;                                                                                         /* add at V1.1 */
> +  for(retrycnt = 0;retrycnt < 4 && pass == 0;retrycnt++){                                           /* add at V1.1 */
> +    min_ddr_vref = 0xFF;
> +    max_ddr_vref = 0x0;
> +    pass = 0;
> +    for(ddr_vref = 0x00;ddr_vref < 0x40;ddr_vref++){
> +      ast_moutdwm(ast, 0x1E6E000C,0x00000000);
> +      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> +      ast_moutdwm(ast, 0x1E6E02C0,0x00000006 | (ddr_vref << 8));
> +      /* Fire DFI Init */
> +      Do_DDRPHY_Init(ast);
> +      ast_moutdwm(ast, 0x1E6E000C,0x00005C01);
> +      if(CBRTest_AST2500(ast)){
> +        pass++;
> +        if(min_ddr_vref > ddr_vref){
> +          min_ddr_vref = ddr_vref;
> +        }
> +        if(max_ddr_vref < ddr_vref){
> +          max_ddr_vref = ddr_vref;
> +        }
> +      }else if(pass != 0){
> +        break;
> +      }
> +    }
> +  }                                                                                                 /* add at V1.1 */
> +  ast_moutdwm(ast, 0x1E6E000C,0x00000000);
> +  ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> +  ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
> +  ast_moutdwm(ast, 0x1E6E02C0,0x00000006 | (ddr_vref << 8));
> +
> +  /* Wait DDR PHY init done */
> +  Do_DDRPHY_Init(ast);
> +
> +  ast_moutdwm(ast, 0x1E6E0120,ddr_table[REGIDX_PLL]);
> +  ast_moutdwm(ast, 0x1E6E000C,0x42AA5C81);
> +  ast_moutdwm(ast, 0x1E6E0034,0x0001AF93);
> +
> +  Check_DRAM_Size(ast, ddr_table[REGIDX_RFC]);
> +  Enable_Cache(ast);
> +  ast_moutdwm(ast, 0x1E6E001C,0x00000008);
> +  ast_moutdwm(ast, 0x1E6E0038,0xFFFFFF00);
> +}
> +
> +static u32 DRAM_Init_AST2500(struct ast_private *ast)
> +{
> +  u32 data;
> +
> +START_INIT:
> +  Set_MPLL(ast);
> +  Reset_MMC(ast);
> +  DDR_Init_Common(ast);
> +  data = ast_mindwm(ast, 0x1E6E2070);
> +  if(data & 0x01000000){
> +    DDR4_Init_AST2500(ast, ddr4_1600_timing_table);
> +  }else{
> +    DDR3_Init_AST2500(ast, ddr3_1600_timing_table);
> +  }
> +  if(!DDRTest_AST2500(ast)){                                                                      /* add at V1.1 */
> +    goto START_INIT;                                                                              /* add at V1.1 */
> +  }
> +  ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) | 0x41);
> +  /* Patch code */
> +  data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
> +  ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
> +  return(1);
> +}
> +
> +static void ast_init_dram_2500(struct drm_device *dev)
> +{
> +       struct ast_private *ast = dev->dev_private;
> +       u32 temp;
> +       u8 reg;
> +
> +       reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
> +       if ((reg & 0x80) == 0) {/* vga only */
> +               /************************************************************************************************/
> +               /* Below patch should be executed at the first time before any access to AST25xx                */
> +               /* Clear bus lock condition */
> +               ast_moutdwm(ast, 0x1e600000,0xAEED1A03);                                                         /* add at V1.1 */
> +               ast_moutdwm(ast, 0x1e600084,0x00010000);                                                         /* add at V1.1 */
> +               ast_moutdwm(ast, 0x1e600088,0x00000000);                                                         /* add at V1.1 */
> +               ast_moutdwm(ast, 0x1e6e2000,0x1688A8A8);                                                         /* add at V1.1 */
> +               /************************************************************************************************/
> +
> +               ast_write32(ast, 0xf004, 0x1e6e0000);
> +               ast_write32(ast, 0xf000, 0x1);
> +               ast_write32(ast, 0x12000, 0x1688a8a8);
> +               do {
> +                       ;
> +               } while (ast_read32(ast, 0x12000) != 0x1);
> +
> +               ast_write32(ast, 0x10000, 0xfc600309);
> +               do {
> +                       ;
> +               } while (ast_read32(ast, 0x10000) != 0x1);
> +
> +               /* Slow down CPU/AHB CLK in VGA only mode */
> +               temp = ast_read32(ast, 0x12008);
> +               temp |= 0x73;
> +               ast_write32(ast, 0x12008, temp);
> +
> +               /* Reset USB port to patch USB unknown device issue */
> +               ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
> +       temp  = ast_mindwm(ast, 0x1e6e2094);
> +       temp |= 0x00004000;
> +       ast_moutdwm(ast, 0x1e6e2094, temp);
> +       temp  = ast_mindwm(ast, 0x1e6e2070);
> +               if (temp & 0x00800000)
> +               {
> +               ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
> +                       mdelay(100);                                                    /* delay 100ms */
> +               ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
> +               }
> +
> +               DRAM_Init_AST2500(ast);
> +
> +               temp = ast_mindwm(ast, 0x1e6e2040);
> +               ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
> +       }
> +
> +       /* wait ready */
> +       do {
> +               reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
> +       } while ((reg & 0x40) == 0);
> +}
> diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h
> index 3608d5a..24da4c2 100644
> --- a/drivers/gpu/drm/ast/ast_tables.h
> +++ b/drivers/gpu/drm/ast/ast_tables.h
> @@ -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 @@
>         {0x3b, 0x2c, 0x81},                                     /* 1A: VCLK118_25       */
>  };
>
> +static 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 struct ast_vbios_stdtable vbios_stdtable[] = {
>         /* MD_2_3_400 */
>         {
> @@ -244,32 +275,32 @@
>  /* 16:9 */
>  static 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 },
> +        (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | AST2500PreCatchCRT), 60, 1, 0x39 },
>         {1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,          /* end */
>          (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 },
>  };
>
>  static 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 },
> -       {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 */
> -        (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 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 */
> +     (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x3A },
>  };
>
>  static 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 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 +310,7 @@
>
>  static 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 +319,7 @@
>
>  static 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 +328,9 @@
>
>  static 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
> --
> 1.8.3.1
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
Benjamin Herrenschmidt Feb. 16, 2017, 5:50 a.m. UTC | #3
On Thu, 2017-02-16 at 14:24 +1000, Dave Airlie wrote:
> On 11 January 2017 at 12:57, Y.C. Chen <yc_chen@aspeedtech.com>
> wrote:
> > From: "Y.C. Chen" <yc_chen@aspeedtech.com>
> 
> Please run checkpatch over this patch, it's got a lot of bad
> whitespace issues
> (4 space and 2 space indents, indent the timing tables , remove start
> of line whitespace.).

It's also misdetecting VRAM on my 2500 based POWER9 boxes. I'll take
over the patch, make it work and clean it up. Along with fixing the
P2A business properly.

New patch tomorrow hopefully.

Cheers,
Ben.

> 
> Dave.
> 
> > 
> > Signed-off-by: Y.C. Chen <yc_chen@aspeedtech.com>
> > ---
> >  drivers/gpu/drm/ast/ast_drv.h    |   2 +
> >  drivers/gpu/drm/ast/ast_main.c   |  27 ++-
> >  drivers/gpu/drm/ast/ast_mode.c   |  25 +-
> >  drivers/gpu/drm/ast/ast_post.c   | 510
> > ++++++++++++++++++++++++++++++++++++++-
> >  drivers/gpu/drm/ast/ast_tables.h |  57 ++++-
> >  5 files changed, 596 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/ast/ast_drv.h
> > b/drivers/gpu/drm/ast/ast_drv.h
> > index 908011d..7e406ce 100644
> > --- a/drivers/gpu/drm/ast/ast_drv.h
> > +++ b/drivers/gpu/drm/ast/ast_drv.h
> > @@ -64,6 +64,7 @@ enum ast_chip {
> >         AST2150,
> >         AST2300,
> >         AST2400,
> > +       AST2500,
> >         AST1180,
> >  };
> > 
> > @@ -80,6 +81,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;
> > 
> > diff --git a/drivers/gpu/drm/ast/ast_main.c
> > b/drivers/gpu/drm/ast/ast_main.c
> > index f75c642..40460ce 100644
> > --- a/drivers/gpu/drm/ast/ast_main.c
> > +++ b/drivers/gpu/drm/ast/ast_main.c
> > @@ -73,7 +73,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) {
> > @@ -149,6 +152,8 @@ static int ast_detect_chip(struct drm_device
> > *dev, bool *need_post)
> >                                 ast->support_wide_screen = true;
> >                         if (ast->chip == AST2400 && data == 0x100)
> > /* ast1400 */
> >                                 ast->support_wide_screen = true;
> > +                       if (ast->chip == AST2500 && data == 0x100)
> > /* ast2510 */
> > +                               ast->support_wide_screen = true;
> >                 }
> >                 break;
> >         }
> > @@ -233,7 +238,24 @@ 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 (data & 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 (data & 0x03) {
> >                 case 0:
> >                         ast->dram_type = AST_DRAM_512Mx16;
> > @@ -456,6 +478,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;
> > diff --git a/drivers/gpu/drm/ast/ast_mode.c
> > b/drivers/gpu/drm/ast/ast_mode.c
> > index e26c98f..242ca7f 100644
> > --- a/drivers/gpu/drm/ast/ast_mode.c
> > +++ b/drivers/gpu/drm/ast/ast_mode.c
> > @@ -271,7 +271,10 @@ 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);
> > 
> > @@ -297,12 +300,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));
> > @@ -363,6 +366,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);
> >  }
> > 
> > @@ -383,12 +391,15 @@ static void ast_set_dclk_reg(struct
> > drm_device *dev, struct drm_display_mode *mo
> >         struct ast_private *ast = dev->dev_private;
> >         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,
> > @@ -421,7 +432,7 @@ 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 ||
> > @@ -794,7 +805,7 @@ 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;
> > 
> > diff --git a/drivers/gpu/drm/ast/ast_post.c
> > b/drivers/gpu/drm/ast/ast_post.c
> > index 810c51d..05d7d36 100644
> > --- a/drivers/gpu/drm/ast/ast_post.c
> > +++ b/drivers/gpu/drm/ast/ast_post.c
> > @@ -32,6 +32,7 @@
> >  #include "ast_dram_tables.h"
> > 
> >  static void ast_init_dram_2300(struct drm_device *dev);
> > +static void ast_init_dram_2500(struct drm_device *dev);
> > 
> >  void ast_enable_vga(struct drm_device *dev)
> >  {
> > @@ -82,7 +83,7 @@ bool ast_is_vga_enabled(struct drm_device *dev)
> >         for (i = 0x81; i <= 0x8f; i++)
> >                 ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
> > 
> > -       if (ast->chip == AST2300 || ast->chip == AST2400) {
> > +       if (ast->chip == AST2300 || ast->chip == AST2400 || ast-
> > >chip == AST2500) {
> >                 if (dev->pdev->revision >= 0x20)
> >                         ext_reg_info = extreginfo_ast2300;
> >                 else
> > @@ -106,7 +107,7 @@ bool ast_is_vga_enabled(struct drm_device *dev)
> > 
> >         /* Enable RAMDAC for A1 */
> >         reg = 0x04;
> > -       if (ast->chip == AST2300 || ast->chip == AST2400)
> > +       if (ast->chip == AST2300 || ast->chip == AST2400 || ast-
> > >chip == AST2500)
> >                 reg |= 0x20;
> >         ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff,
> > reg);
> >  }
> > @@ -379,7 +380,9 @@ void ast_post_gpu(struct drm_device *dev)
> >         ast_open_key(ast);
> >         ast_set_def_ext_reg(dev);
> > 
> > -       if (ast->chip == AST2300 || ast->chip == AST2400)
> > +       if (ast->chip == AST2500)
> > +               ast_init_dram_2500(dev);
> > +       else if (ast->chip == AST2300 || ast->chip == AST2400)
> >                 ast_init_dram_2300(dev);
> >         else
> >                 ast_init_dram_reg(dev);
> > @@ -1655,3 +1658,504 @@ static void ast_init_dram_2300(struct
> > drm_device *dev)
> >         } while ((reg & 0x40) == 0);
> >  }
> > 
> > +/*
> > + * AST2500 DRAM settings modules
> > + */
> > +#define REGTBL_NUM           17
> > +#define REGIDX_010           0
> > +#define REGIDX_014           1
> > +#define REGIDX_018           2
> > +#define REGIDX_020           3
> > +#define REGIDX_024           4
> > +#define REGIDX_02C           5
> > +#define REGIDX_030           6
> > +#define REGIDX_214           7
> > +#define REGIDX_2E0           8
> > +#define REGIDX_2E4           9
> > +#define REGIDX_2E8           10
> > +#define REGIDX_2EC           11
> > +#define REGIDX_2F0           12
> > +#define REGIDX_2F4           13
> > +#define REGIDX_2F8           14
> > +#define REGIDX_RFC           15
> > +#define REGIDX_PLL           16
> > +
> > +static u32 ddr3_1600_timing_table[REGTBL_NUM] = {
> > +0x64604D38,                  /* 0x010 */
> > +0x29690599,                  /* 0x014 */
> > +0x00000300,                  /* 0x018 */
> > +0x00000000,                  /* 0x020 */
> > +0x00000000,                  /* 0x024 */
> > +0x02181E70,                  /* 0x02C */
> > +0x00000040,                  /* 0x030 */
> > +0x00000024,                  /* 0x214 */
> > +0x02001300,                  /* 0x2E0 */
> > +0x0E0000A0,                  /* 0x2E4 */
> > +0x000E001B,                  /* 0x2E8 */
> > +0x35B8C105,                  /* 0x2EC */
> > +0x08090408,                  /* 0x2F0 */
> > +0x9B000800,                  /* 0x2F4 */
> > +0x0E400A00,                  /* 0x2F8 */
> > +0x9971452F,                  /* tRFC  */
> > +0x000071C1};                 /* PLL   */
> > +
> > +static u32 ddr4_1600_timing_table[REGTBL_NUM] = {
> > +0x63604E37,                  /* 0x010 */
> > +0xE97AFA99,                  /* 0x014 */
> > +0x00019000,                  /* 0x018 */
> > +0x08000000,                  /* 0x020 */
> > +0x00000400,                  /* 0x024 */
> > +0x00000410,                  /* 0x02C */
> > +0x00000101,                  /* 0x030 */
> > +0x00000024,                  /* 0x214 */
> > +0x03002900,                  /* 0x2E0 */
> > +0x0E0000A0,                  /* 0x2E4 */
> > +0x000E001C,                  /* 0x2E8 */
> > +0x35B8C106,                  /* 0x2EC */
> > +0x08080607,                  /* 0x2F0 */
> > +0x9B000900,                  /* 0x2F4 */
> > +0x0E400A00,                  /* 0x2F8 */
> > +0x99714545,                  /* tRFC  */
> > +0x000071C1};                 /* PLL   */
> > +
> > +static u32 MMCTestBurst_AST2500(struct ast_private *ast, u32
> > datagen)
> > +{
> > +  u32 data, timecnt;
> > +
> > +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0070, 0x000000C1 | (datagen << 3));
> > +  timecnt = 0;
> > +  do{
> > +    data = ast_mindwm(ast, 0x1E6E0070) & 0x3000;
> > +    if(data & 0x2000){
> > +      return(0);
> > +    }
> > +    if(++timecnt > TIMEOUT){
> > +      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> > +      return(0);
> > +    }
> > +  }while(!data);
> > +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> > +  return(1);
> > +}
> > +
> > +static u32 MMCTestSingle_AST2500(struct ast_private *ast, u32
> > datagen)
> > +{
> > +  u32 data, timecnt;
> > +
> > +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0070, 0x00000085 | (datagen << 3));
> > +  timecnt = 0;
> > +  do{
> > +    data = ast_mindwm(ast, 0x1E6E0070) & 0x3000;
> > +    if(data & 0x2000){
> > +      return(0);
> > +    }
> > +    if(++timecnt > TIMEOUT){
> > +      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> > +      return(0);
> > +    }
> > +  }while(!data);
> > +  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
> > +  return(1);
> > +}
> > +
> > +static u32 CBRTest_AST2500(struct ast_private *ast)
> > +{
> > +  ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
> > +  ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
> > +  if(!MMCTestBurst_AST2500(ast, 0)) return(0);
> > +  if(!MMCTestSingle_AST2500(ast, 0)) return(0);
> > +  return(1);
> > +}
> > +
> > +static bool DDRTest_AST2500(struct ast_private *ast)
> > +{
> > +  ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
> > +  ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
> > +  if(!MMCTestBurst_AST2500(ast, 0)) return(0);
> > +  if(!MMCTestBurst_AST2500(ast, 1)) return(0);
> > +  if(!MMCTestBurst_AST2500(ast, 2)) return(0);
> > +  if(!MMCTestBurst_AST2500(ast, 3)) return(0);
> > +  if(!MMCTestSingle_AST2500(ast, 0)) return(0);
> > +  return(1);
> > +}
> > +
> > +static void DDR_Init_Common(struct ast_private *ast)
> > +{
> > +  ast_moutdwm(ast, 0x1E6E0034,0x00020080);
> > +  ast_moutdwm(ast, 0x1E6E0008,0x2003000F);
> > +  ast_moutdwm(ast, 0x1E6E0038,0x00000FFF);
> > +  ast_moutdwm(ast, 0x1E6E0040,0x88448844);
> > +  ast_moutdwm(ast, 0x1E6E0044,0x24422288);
> > +  ast_moutdwm(ast, 0x1E6E0048,0x22222222);
> > +  ast_moutdwm(ast, 0x1E6E004C,0x22222222);
> > +  ast_moutdwm(ast, 0x1E6E0050,0x80000000);
> > +  ast_moutdwm(ast, 0x1E6E0208,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0218,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0220,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0228,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0230,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E02A8,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E02B0,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0240,0x86000000);
> > +  ast_moutdwm(ast, 0x1E6E0244,0x00008600);
> > +  ast_moutdwm(ast, 0x1E6E0248,0x80000000);
> > +  ast_moutdwm(ast, 0x1E6E024C,0x80808080);
> > +}
> > +
> > +static void Do_DDRPHY_Init(struct ast_private *ast)
> > +{
> > +  u32 data, pass, timecnt;
> > +
> > +  pass = 0;
> > +  ast_moutdwm(ast, 0x1E6E0060,0x00000005);
> > +  while(!pass){
> > +    for(timecnt = 0;timecnt < TIMEOUT;timecnt++){
> > +      data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
> > +      if(!data){
> > +        break;
> > +      }
> > +    }
> > +    if(timecnt != TIMEOUT){
> > +      data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
> > +      if(!data){
> > +        pass = 1;
> > +      }
> > +    }
> > +    if(!pass){
> > +      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> > +      udelay(10); /* delay 10 us */
> > +      ast_moutdwm(ast, 0x1E6E0060,0x00000005);
> > +    }
> > +  }
> > +
> > +  ast_moutdwm(ast, 0x1E6E0060,0x00000006);
> > +}
> > +
> > +/*****************************************************************
> > *************
> > + Check DRAM Size
> > + 1Gb : 0x80000000 ~ 0x87FFFFFF
> > + 2Gb : 0x80000000 ~ 0x8FFFFFFF
> > + 4Gb : 0x80000000 ~ 0x9FFFFFFF
> > + 8Gb : 0x80000000 ~ 0xBFFFFFFF
> > +
> > *******************************************************************
> > **********/
> > +static void Check_DRAM_Size(struct ast_private *ast, u32 tRFC)
> > +{
> > +  u32 reg_04, reg_14;
> > +
> > +  reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
> > +  reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
> > +
> > +  ast_moutdwm(ast, 0xA0100000, 0x41424344);
> > +  ast_moutdwm(ast, 0x90100000, 0x35363738);
> > +  ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
> > +  ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
> > +
> > +  /* Check 8Gbit */
> > +  if(ast_mindwm(ast, 0xA0100000) == 0x41424344){
> > +    reg_04 |= 0x03;
> > +    reg_14 |= (tRFC >> 24) & 0xFF;
> > +  /* Check 4Gbit */
> > +  }else if(ast_mindwm(ast, 0x90100000) == 0x35363738){
> > +    reg_04 |= 0x02;
> > +    reg_14 |= (tRFC >> 16) & 0xFF;
> > +  /* Check 2Gbit */
> > +  }else if(ast_mindwm(ast, 0x88100000) == 0x292A2B2C){
> > +    reg_04 |= 0x01;
> > +    reg_14 |= (tRFC >> 8) & 0xFF;
> > +  }else{
> > +    reg_14 |= tRFC & 0xFF;
> > +  }
> > +  ast_moutdwm(ast, 0x1E6E0004, reg_04);
> > +  ast_moutdwm(ast, 0x1E6E0014, reg_14);
> > +}
> > +
> > +static void Enable_Cache(struct ast_private *ast)
> > +{
> > +  u32 reg_04, data;
> > +
> > +  reg_04 = ast_mindwm(ast, 0x1E6E0004);
> > +  ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
> > +
> > +  do{
> > +    data = ast_mindwm(ast, 0x1E6E0004);
> > +  }while(!(data & 0x80000));
> > +  ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
> > +}
> > +
> > +static void Set_MPLL(struct ast_private *ast)
> > +{
> > +  u32 addr, data, param;
> > +
> > +  /* Reset MMC */
> > +  ast_moutdwm(ast, 0x1E6E0000,0xFC600309);
> > +  ast_moutdwm(ast, 0x1E6E0034,0x00020080);
> > +  for(addr = 0x1e6e0004;addr < 0x1e6e0090;){
> > +    ast_moutdwm(ast, addr, 0x0);
> > +    addr += 4;
> > +  }
> > +  ast_moutdwm(ast, 0x1E6E0034,0x00020000);
> > +
> > +  ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
> > +  data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
> > +  if(data){                  /* CLKIN = 25MHz */
> > +    param = 0x930023E0;
> > +    ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
> > +  }else{                                        /* CLKIN = 24MHz
> > */
> > +    param = 0x93002400;
> > +  }
> > +  ast_moutdwm(ast, 0x1E6E2020, param);
> > +  udelay(100);
> > +}
> > +
> > +static void Reset_MMC(struct ast_private *ast)
> > +{
> > +  ast_moutdwm(ast, 0x1E78505C,0x00000004);
> > +  ast_moutdwm(ast, 0x1E785044,0x00000001);
> > +  ast_moutdwm(ast, 0x1E785048,0x00004755);
> > +  ast_moutdwm(ast, 0x1E78504C,0x00000013);
> > +  mdelay(100);                                 /* delay 100ms */
> > +  ast_moutdwm(ast, 0x1E785054,0x00000077);
> > +  ast_moutdwm(ast, 0x1E6E0000,0xFC600309);
> > +}
> > +
> > +static void DDR3_Init_AST2500(struct ast_private *ast, u32
> > *ddr_table)
> > +{
> > +
> > +  ast_moutdwm(ast, 0x1E6E0004,0x00000303);
> > +  ast_moutdwm(ast, 0x1E6E0010,ddr_table[REGIDX_010]);
> > +  ast_moutdwm(ast, 0x1E6E0014,ddr_table[REGIDX_014]);
> > +  ast_moutdwm(ast, 0x1E6E0018,ddr_table[REGIDX_018]);
> > +  ast_moutdwm(ast, 0x1E6E0020,ddr_table[REGIDX_020]);          /*
> > MODEREG4/6 */
> > +  ast_moutdwm(ast, 0x1E6E0024,ddr_table[REGIDX_024]);          /*
> > MODEREG5 */
> > +  ast_moutdwm(ast, 0x1E6E002C,ddr_table[REGIDX_02C] | 0x100);  /*
> > MODEREG0/2 */
> > +  ast_moutdwm(ast, 0x1E6E0030,ddr_table[REGIDX_030]);          /*
> > MODEREG1/3 */
> > +
> > +  /* DDR PHY Setting */
> > +  ast_moutdwm(ast, 0x1E6E0200,0x02492AAE);
> > +  ast_moutdwm(ast, 0x1E6E0204,0x00001001);
> > +  ast_moutdwm(ast, 0x1E6E020C,0x55E00B0B);
> > +  ast_moutdwm(ast, 0x1E6E0210,0x20000000);
> > +  ast_moutdwm(ast, 0x1E6E0214,ddr_table[REGIDX_214]);
> > +  ast_moutdwm(ast, 0x1E6E02E0,ddr_table[REGIDX_2E0]);
> > +  ast_moutdwm(ast, 0x1E6E02E4,ddr_table[REGIDX_2E4]);
> > +  ast_moutdwm(ast, 0x1E6E02E8,ddr_table[REGIDX_2E8]);
> > +  ast_moutdwm(ast, 0x1E6E02EC,ddr_table[REGIDX_2EC]);
> > +  ast_moutdwm(ast, 0x1E6E02F0,ddr_table[REGIDX_2F0]);
> > +  ast_moutdwm(ast, 0x1E6E02F4,ddr_table[REGIDX_2F4]);
> > +  ast_moutdwm(ast, 0x1E6E02F8,ddr_table[REGIDX_2F8]);
> > +  ast_moutdwm(ast, 0x1E6E0290,0x00100008);
> > +  ast_moutdwm(ast, 0x1E6E02C0,0x00000006);
> > +
> > +  /* Controller Setting */
> > +  ast_moutdwm(ast, 0x1E6E0034,0x00020091);
> > +
> > +  /* Wait DDR PHY init done */
> > +  Do_DDRPHY_Init(ast);
> > +
> > +  ast_moutdwm(ast, 0x1E6E0120,ddr_table[REGIDX_PLL]);
> > +  ast_moutdwm(ast, 0x1E6E000C,0x42AA5C81);
> > +  ast_moutdwm(ast, 0x1E6E0034,0x0001AF93);
> > +
> > +  Check_DRAM_Size(ast, ddr_table[REGIDX_RFC]);
> > +  Enable_Cache(ast);
> > +  ast_moutdwm(ast, 0x1E6E001C,0x00000008);
> > +  ast_moutdwm(ast, 0x1E6E0038,0xFFFFFF00);
> > +}
> > +
> > +static void DDR4_Init_AST2500(struct ast_private *ast, u32
> > *ddr_table)
> > +{
> > +  u32 data, data2, pass, retrycnt;
> > +  u32 ddr_vref, phy_vref;
> > +  u32 min_ddr_vref=0, min_phy_vref=0;
> > +  u32 max_ddr_vref=0, max_phy_vref=0;
> > +
> > +  ast_moutdwm(ast, 0x1E6E0004,0x00000313);
> > +  ast_moutdwm(ast, 0x1E6E0010,ddr_table[REGIDX_010]);
> > +  ast_moutdwm(ast, 0x1E6E0014,ddr_table[REGIDX_014]);
> > +  ast_moutdwm(ast, 0x1E6E0018,ddr_table[REGIDX_018]);
> > +  ast_moutdwm(ast, 0x1E6E0020,ddr_table[REGIDX_020]);          /*
> > MODEREG4/6 */
> > +  ast_moutdwm(ast, 0x1E6E0024,ddr_table[REGIDX_024]);          /*
> > MODEREG5 */
> > +  ast_moutdwm(ast, 0x1E6E002C,ddr_table[REGIDX_02C] | 0x100);  /*
> > MODEREG0/2 */
> > +  ast_moutdwm(ast, 0x1E6E0030,ddr_table[REGIDX_030]);          /*
> > MODEREG1/3 */
> > +
> > +  /* DDR PHY Setting */
> > +  ast_moutdwm(ast, 0x1E6E0200,0x42492AAE);
> > +  ast_moutdwm(ast, 0x1E6E0204,0x09002000);
> > +  ast_moutdwm(ast, 0x1E6E020C,0x55E00B0B);
> > +  ast_moutdwm(ast, 0x1E6E0210,0x20000000);
> > +  ast_moutdwm(ast, 0x1E6E0214,ddr_table[REGIDX_214]);
> > +  ast_moutdwm(ast, 0x1E6E02E0,ddr_table[REGIDX_2E0]);
> > +  ast_moutdwm(ast, 0x1E6E02E4,ddr_table[REGIDX_2E4]);
> > +  ast_moutdwm(ast, 0x1E6E02E8,ddr_table[REGIDX_2E8]);
> > +  ast_moutdwm(ast, 0x1E6E02EC,ddr_table[REGIDX_2EC]);
> > +  ast_moutdwm(ast, 0x1E6E02F0,ddr_table[REGIDX_2F0]);
> > +  ast_moutdwm(ast, 0x1E6E02F4,ddr_table[REGIDX_2F4]);
> > +  ast_moutdwm(ast, 0x1E6E02F8,ddr_table[REGIDX_2F8]);
> > +  ast_moutdwm(ast, 0x1E6E0290,0x00100008);
> > +  ast_moutdwm(ast, 0x1E6E02C4,0x3C183C3C);
> > +  ast_moutdwm(ast, 0x1E6E02C8,0x00631E0E);
> > +
> > +  /* Controller Setting */
> > +  ast_moutdwm(ast, 0x1E6E0034,0x0001A991);
> > +
> > +  /* Train PHY Vref first */
> > +  pass =
> > 0;                                                                 
> >                         /* add at V1.1 */
> > +  for(retrycnt = 0;retrycnt < 4 && pass ==
> > 0;retrycnt++){                                           /* add at
> > V1.1 */
> > +    max_phy_vref = 0x0;
> > +    pass = 0;
> > +    ast_moutdwm(ast, 0x1E6E02C0,0x00001C06);
> > +    for(phy_vref = 0x40;phy_vref < 0x80;phy_vref++){
> > +      ast_moutdwm(ast, 0x1E6E000C,0x00000000);
> > +      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> > +      ast_moutdwm(ast, 0x1E6E02CC,phy_vref | (phy_vref << 8));
> > +      /* Fire DFI Init */
> > +      Do_DDRPHY_Init(ast);
> > +      ast_moutdwm(ast, 0x1E6E000C,0x00005C01);
> > +      if(CBRTest_AST2500(ast)){
> > +        pass++;
> > +        data = ast_mindwm(ast, 0x1E6E03D0);
> > +        data2 = data >> 8;
> > +        data  = data & 0xff;
> > +        if(data > data2){
> > +          data = data2;
> > +        }
> > +
> > +        if(max_phy_vref < data){
> > +          max_phy_vref = data;
> > +          min_phy_vref = phy_vref;
> > +        }
> > +      }else if(pass > 0){
> > +        break;
> > +      }
> > +    }
> > +  }                                                               
> >                                   /* add at V1.1 */
> > +  ast_moutdwm(ast, 0x1E6E02CC,min_phy_vref | (min_phy_vref << 8));
> > +
> > +  /* Train DDR Vref next */
> > +  pass =
> > 0;                                                                 
> >                         /* add at V1.1 */
> > +  for(retrycnt = 0;retrycnt < 4 && pass ==
> > 0;retrycnt++){                                           /* add at
> > V1.1 */
> > +    min_ddr_vref = 0xFF;
> > +    max_ddr_vref = 0x0;
> > +    pass = 0;
> > +    for(ddr_vref = 0x00;ddr_vref < 0x40;ddr_vref++){
> > +      ast_moutdwm(ast, 0x1E6E000C,0x00000000);
> > +      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> > +      ast_moutdwm(ast, 0x1E6E02C0,0x00000006 | (ddr_vref << 8));
> > +      /* Fire DFI Init */
> > +      Do_DDRPHY_Init(ast);
> > +      ast_moutdwm(ast, 0x1E6E000C,0x00005C01);
> > +      if(CBRTest_AST2500(ast)){
> > +        pass++;
> > +        if(min_ddr_vref > ddr_vref){
> > +          min_ddr_vref = ddr_vref;
> > +        }
> > +        if(max_ddr_vref < ddr_vref){
> > +          max_ddr_vref = ddr_vref;
> > +        }
> > +      }else if(pass != 0){
> > +        break;
> > +      }
> > +    }
> > +  }                                                               
> >                                   /* add at V1.1 */
> > +  ast_moutdwm(ast, 0x1E6E000C,0x00000000);
> > +  ast_moutdwm(ast, 0x1E6E0060,0x00000000);
> > +  ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
> > +  ast_moutdwm(ast, 0x1E6E02C0,0x00000006 | (ddr_vref << 8));
> > +
> > +  /* Wait DDR PHY init done */
> > +  Do_DDRPHY_Init(ast);
> > +
> > +  ast_moutdwm(ast, 0x1E6E0120,ddr_table[REGIDX_PLL]);
> > +  ast_moutdwm(ast, 0x1E6E000C,0x42AA5C81);
> > +  ast_moutdwm(ast, 0x1E6E0034,0x0001AF93);
> > +
> > +  Check_DRAM_Size(ast, ddr_table[REGIDX_RFC]);
> > +  Enable_Cache(ast);
> > +  ast_moutdwm(ast, 0x1E6E001C,0x00000008);
> > +  ast_moutdwm(ast, 0x1E6E0038,0xFFFFFF00);
> > +}
> > +
> > +static u32 DRAM_Init_AST2500(struct ast_private *ast)
> > +{
> > +  u32 data;
> > +
> > +START_INIT:
> > +  Set_MPLL(ast);
> > +  Reset_MMC(ast);
> > +  DDR_Init_Common(ast);
> > +  data = ast_mindwm(ast, 0x1E6E2070);
> > +  if(data & 0x01000000){
> > +    DDR4_Init_AST2500(ast, ddr4_1600_timing_table);
> > +  }else{
> > +    DDR3_Init_AST2500(ast, ddr3_1600_timing_table);
> > +  }
> > +  if(!DDRTest_AST2500(ast)){                                      
> >                                 /* add at V1.1 */
> > +    goto
> > START_INIT;                                                        
> >                       /* add at V1.1 */
> > +  }
> > +  ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) |
> > 0x41);
> > +  /* Patch code */
> > +  data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
> > +  ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
> > +  return(1);
> > +}
> > +
> > +static void ast_init_dram_2500(struct drm_device *dev)
> > +{
> > +       struct ast_private *ast = dev->dev_private;
> > +       u32 temp;
> > +       u8 reg;
> > +
> > +       reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0,
> > 0xff);
> > +       if ((reg & 0x80) == 0) {/* vga only */
> > +               /**************************************************
> > **********************************************/
> > +               /* Below patch should be executed at the first time
> > before any access to AST25xx                */
> > +               /* Clear bus lock condition */
> > +               ast_moutdwm(ast,
> > 0x1e600000,0xAEED1A03);                                            
> >              /* add at V1.1 */
> > +               ast_moutdwm(ast,
> > 0x1e600084,0x00010000);                                            
> >              /* add at V1.1 */
> > +               ast_moutdwm(ast,
> > 0x1e600088,0x00000000);                                            
> >              /* add at V1.1 */
> > +               ast_moutdwm(ast,
> > 0x1e6e2000,0x1688A8A8);                                            
> >              /* add at V1.1 */
> > +               /**************************************************
> > **********************************************/
> > +
> > +               ast_write32(ast, 0xf004, 0x1e6e0000);
> > +               ast_write32(ast, 0xf000, 0x1);
> > +               ast_write32(ast, 0x12000, 0x1688a8a8);
> > +               do {
> > +                       ;
> > +               } while (ast_read32(ast, 0x12000) != 0x1);
> > +
> > +               ast_write32(ast, 0x10000, 0xfc600309);
> > +               do {
> > +                       ;
> > +               } while (ast_read32(ast, 0x10000) != 0x1);
> > +
> > +               /* Slow down CPU/AHB CLK in VGA only mode */
> > +               temp = ast_read32(ast, 0x12008);
> > +               temp |= 0x73;
> > +               ast_write32(ast, 0x12008, temp);
> > +
> > +               /* Reset USB port to patch USB unknown device issue
> > */
> > +               ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
> > +       temp  = ast_mindwm(ast, 0x1e6e2094);
> > +       temp |= 0x00004000;
> > +       ast_moutdwm(ast, 0x1e6e2094, temp);
> > +       temp  = ast_mindwm(ast, 0x1e6e2070);
> > +               if (temp & 0x00800000)
> > +               {
> > +               ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
> > +                       mdelay(100);                               
> >                      /* delay 100ms */
> > +               ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
> > +               }
> > +
> > +               DRAM_Init_AST2500(ast);
> > +
> > +               temp = ast_mindwm(ast, 0x1e6e2040);
> > +               ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
> > +       }
> > +
> > +       /* wait ready */
> > +       do {
> > +               reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT,
> > 0xd0, 0xff);
> > +       } while ((reg & 0x40) == 0);
> > +}
> > diff --git a/drivers/gpu/drm/ast/ast_tables.h
> > b/drivers/gpu/drm/ast/ast_tables.h
> > index 3608d5a..24da4c2 100644
> > --- a/drivers/gpu/drm/ast/ast_tables.h
> > +++ b/drivers/gpu/drm/ast/ast_tables.h
> > @@ -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 @@
> >         {0x3b, 0x2c, 0x81},                                     /*
> > 1A: VCLK118_25       */
> >  };
> > 
> > +static 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 struct ast_vbios_stdtable vbios_stdtable[] = {
> >         /* MD_2_3_400 */
> >         {
> > @@ -244,32 +275,32 @@
> >  /* 16:9 */
> >  static 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 },
> > +        (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode |
> > NewModeInfo | AST2500PreCatchCRT), 60, 1, 0x39 },
> >         {1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,          /*
> > end */
> >          (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode |
> > NewModeInfo), 0xFF, 1, 0x39 },
> >  };
> > 
> >  static 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 },
> > -       {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 */
> > -        (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode |
> > NewModeInfo), 0xFF, 2, 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
> > */
> > +     (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode |
> > NewModeInfo), 0xFF, 2, 0x3A },
> >  };
> > 
> >  static 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 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 +310,7 @@
> > 
> >  static 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 +319,7 @@
> > 
> >  static 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 +328,9 @@
> > 
> >  static 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
> > --
> > 1.8.3.1
> > 
> > _______________________________________________
> > dri-devel mailing list
> > dri-devel@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 908011d..7e406ce 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -64,6 +64,7 @@  enum ast_chip {
 	AST2150,
 	AST2300,
 	AST2400,
+	AST2500,
 	AST1180,
 };
 
@@ -80,6 +81,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;
 
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index f75c642..40460ce 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -73,7 +73,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) {
@@ -149,6 +152,8 @@  static int ast_detect_chip(struct drm_device *dev, bool *need_post)
 				ast->support_wide_screen = true;
 			if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
 				ast->support_wide_screen = true;
+			if (ast->chip == AST2500 && data == 0x100) /* ast2510 */
+				ast->support_wide_screen = true;
 		}
 		break;
 	}
@@ -233,7 +238,24 @@  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 (data & 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 (data & 0x03) {
 		case 0:
 			ast->dram_type = AST_DRAM_512Mx16;
@@ -456,6 +478,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;
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index e26c98f..242ca7f 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -271,7 +271,10 @@  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);
 
@@ -297,12 +300,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));
@@ -363,6 +366,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);
 }
 
@@ -383,12 +391,15 @@  static void ast_set_dclk_reg(struct drm_device *dev, struct drm_display_mode *mo
 	struct ast_private *ast = dev->dev_private;
 	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,
@@ -421,7 +432,7 @@  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 ||
@@ -794,7 +805,7 @@  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;
 
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 810c51d..05d7d36 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -32,6 +32,7 @@ 
 #include "ast_dram_tables.h"
 
 static void ast_init_dram_2300(struct drm_device *dev);
+static void ast_init_dram_2500(struct drm_device *dev);
 
 void ast_enable_vga(struct drm_device *dev)
 {
@@ -82,7 +83,7 @@  bool ast_is_vga_enabled(struct drm_device *dev)
 	for (i = 0x81; i <= 0x8f; i++)
 		ast_set_index_reg(ast, AST_IO_CRTC_PORT, i, 0x00);
 
-	if (ast->chip == AST2300 || ast->chip == AST2400) {
+	if (ast->chip == AST2300 || ast->chip == AST2400 || ast->chip == AST2500) {
 		if (dev->pdev->revision >= 0x20)
 			ext_reg_info = extreginfo_ast2300;
 		else
@@ -106,7 +107,7 @@  bool ast_is_vga_enabled(struct drm_device *dev)
 
 	/* Enable RAMDAC for A1 */
 	reg = 0x04;
-	if (ast->chip == AST2300 || ast->chip == AST2400)
+	if (ast->chip == AST2300 || ast->chip == AST2400 || ast->chip == AST2500)
 		reg |= 0x20;
 	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb6, 0xff, reg);
 }
@@ -379,7 +380,9 @@  void ast_post_gpu(struct drm_device *dev)
 	ast_open_key(ast);
 	ast_set_def_ext_reg(dev);
 
-	if (ast->chip == AST2300 || ast->chip == AST2400)
+	if (ast->chip == AST2500)
+		ast_init_dram_2500(dev);
+	else if (ast->chip == AST2300 || ast->chip == AST2400)
 		ast_init_dram_2300(dev);
 	else
 		ast_init_dram_reg(dev);
@@ -1655,3 +1658,504 @@  static void ast_init_dram_2300(struct drm_device *dev)
 	} while ((reg & 0x40) == 0);
 }
 
+/*
+ * AST2500 DRAM settings modules
+ */
+#define REGTBL_NUM           17
+#define REGIDX_010           0
+#define REGIDX_014           1
+#define REGIDX_018           2
+#define REGIDX_020           3
+#define REGIDX_024           4
+#define REGIDX_02C           5
+#define REGIDX_030           6
+#define REGIDX_214           7
+#define REGIDX_2E0           8
+#define REGIDX_2E4           9
+#define REGIDX_2E8           10
+#define REGIDX_2EC           11
+#define REGIDX_2F0           12
+#define REGIDX_2F4           13
+#define REGIDX_2F8           14
+#define REGIDX_RFC           15
+#define REGIDX_PLL           16
+
+static u32 ddr3_1600_timing_table[REGTBL_NUM] = {
+0x64604D38,                  /* 0x010 */
+0x29690599,                  /* 0x014 */
+0x00000300,                  /* 0x018 */
+0x00000000,                  /* 0x020 */
+0x00000000,                  /* 0x024 */
+0x02181E70,                  /* 0x02C */
+0x00000040,                  /* 0x030 */
+0x00000024,                  /* 0x214 */
+0x02001300,                  /* 0x2E0 */
+0x0E0000A0,                  /* 0x2E4 */
+0x000E001B,                  /* 0x2E8 */
+0x35B8C105,                  /* 0x2EC */
+0x08090408,                  /* 0x2F0 */
+0x9B000800,                  /* 0x2F4 */
+0x0E400A00,                  /* 0x2F8 */
+0x9971452F,                  /* tRFC  */
+0x000071C1};                 /* PLL   */
+
+static u32 ddr4_1600_timing_table[REGTBL_NUM] = {
+0x63604E37,                  /* 0x010 */
+0xE97AFA99,                  /* 0x014 */
+0x00019000,                  /* 0x018 */
+0x08000000,                  /* 0x020 */
+0x00000400,                  /* 0x024 */
+0x00000410,                  /* 0x02C */
+0x00000101,                  /* 0x030 */
+0x00000024,                  /* 0x214 */
+0x03002900,                  /* 0x2E0 */
+0x0E0000A0,                  /* 0x2E4 */
+0x000E001C,                  /* 0x2E8 */
+0x35B8C106,                  /* 0x2EC */
+0x08080607,                  /* 0x2F0 */
+0x9B000900,                  /* 0x2F4 */
+0x0E400A00,                  /* 0x2F8 */
+0x99714545,                  /* tRFC  */
+0x000071C1};                 /* PLL   */
+
+static u32 MMCTestBurst_AST2500(struct ast_private *ast, u32 datagen)
+{
+  u32 data, timecnt;
+
+  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
+  ast_moutdwm(ast, 0x1E6E0070, 0x000000C1 | (datagen << 3));
+  timecnt = 0;
+  do{
+    data = ast_mindwm(ast, 0x1E6E0070) & 0x3000;
+    if(data & 0x2000){
+      return(0);
+    }
+    if(++timecnt > TIMEOUT){
+      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
+      return(0);
+    }
+  }while(!data);
+  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
+  return(1);
+}
+
+static u32 MMCTestSingle_AST2500(struct ast_private *ast, u32 datagen)
+{
+  u32 data, timecnt;
+
+  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
+  ast_moutdwm(ast, 0x1E6E0070, 0x00000085 | (datagen << 3));
+  timecnt = 0;
+  do{
+    data = ast_mindwm(ast, 0x1E6E0070) & 0x3000;
+    if(data & 0x2000){
+      return(0);
+    }
+    if(++timecnt > TIMEOUT){
+      ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
+      return(0);
+    }
+  }while(!data);
+  ast_moutdwm(ast, 0x1E6E0070, 0x00000000);
+  return(1);
+}
+
+static u32 CBRTest_AST2500(struct ast_private *ast)
+{
+  ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
+  ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
+  if(!MMCTestBurst_AST2500(ast, 0)) return(0);
+  if(!MMCTestSingle_AST2500(ast, 0)) return(0);
+  return(1);
+}
+
+static bool DDRTest_AST2500(struct ast_private *ast)
+{
+  ast_moutdwm(ast, 0x1E6E0074, 0x0000FFFF);
+  ast_moutdwm(ast, 0x1E6E007C, 0xFF00FF00);
+  if(!MMCTestBurst_AST2500(ast, 0)) return(0);
+  if(!MMCTestBurst_AST2500(ast, 1)) return(0);
+  if(!MMCTestBurst_AST2500(ast, 2)) return(0);
+  if(!MMCTestBurst_AST2500(ast, 3)) return(0);
+  if(!MMCTestSingle_AST2500(ast, 0)) return(0);
+  return(1);
+}
+
+static void DDR_Init_Common(struct ast_private *ast)
+{
+  ast_moutdwm(ast, 0x1E6E0034,0x00020080);
+  ast_moutdwm(ast, 0x1E6E0008,0x2003000F);
+  ast_moutdwm(ast, 0x1E6E0038,0x00000FFF);
+  ast_moutdwm(ast, 0x1E6E0040,0x88448844);
+  ast_moutdwm(ast, 0x1E6E0044,0x24422288);
+  ast_moutdwm(ast, 0x1E6E0048,0x22222222);
+  ast_moutdwm(ast, 0x1E6E004C,0x22222222);
+  ast_moutdwm(ast, 0x1E6E0050,0x80000000);
+  ast_moutdwm(ast, 0x1E6E0208,0x00000000);
+  ast_moutdwm(ast, 0x1E6E0218,0x00000000);
+  ast_moutdwm(ast, 0x1E6E0220,0x00000000);
+  ast_moutdwm(ast, 0x1E6E0228,0x00000000);
+  ast_moutdwm(ast, 0x1E6E0230,0x00000000);
+  ast_moutdwm(ast, 0x1E6E02A8,0x00000000);
+  ast_moutdwm(ast, 0x1E6E02B0,0x00000000);
+  ast_moutdwm(ast, 0x1E6E0240,0x86000000);
+  ast_moutdwm(ast, 0x1E6E0244,0x00008600);
+  ast_moutdwm(ast, 0x1E6E0248,0x80000000);
+  ast_moutdwm(ast, 0x1E6E024C,0x80808080);
+}
+
+static void Do_DDRPHY_Init(struct ast_private *ast)
+{
+  u32 data, pass, timecnt;
+
+  pass = 0;
+  ast_moutdwm(ast, 0x1E6E0060,0x00000005);
+  while(!pass){
+    for(timecnt = 0;timecnt < TIMEOUT;timecnt++){
+      data = ast_mindwm(ast, 0x1E6E0060) & 0x1;
+      if(!data){
+        break;
+      }
+    }
+    if(timecnt != TIMEOUT){
+      data = ast_mindwm(ast, 0x1E6E0300) & 0x000A0000;
+      if(!data){
+        pass = 1;
+      }
+    }
+    if(!pass){
+      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
+      udelay(10); /* delay 10 us */
+      ast_moutdwm(ast, 0x1E6E0060,0x00000005);
+    }
+  }
+
+  ast_moutdwm(ast, 0x1E6E0060,0x00000006);
+}
+
+/******************************************************************************
+ Check DRAM Size
+ 1Gb : 0x80000000 ~ 0x87FFFFFF
+ 2Gb : 0x80000000 ~ 0x8FFFFFFF
+ 4Gb : 0x80000000 ~ 0x9FFFFFFF
+ 8Gb : 0x80000000 ~ 0xBFFFFFFF
+ *****************************************************************************/
+static void Check_DRAM_Size(struct ast_private *ast, u32 tRFC)
+{
+  u32 reg_04, reg_14;
+
+  reg_04 = ast_mindwm(ast, 0x1E6E0004) & 0xfffffffc;
+  reg_14 = ast_mindwm(ast, 0x1E6E0014) & 0xffffff00;
+
+  ast_moutdwm(ast, 0xA0100000, 0x41424344);
+  ast_moutdwm(ast, 0x90100000, 0x35363738);
+  ast_moutdwm(ast, 0x88100000, 0x292A2B2C);
+  ast_moutdwm(ast, 0x80100000, 0x1D1E1F10);
+
+  /* Check 8Gbit */
+  if(ast_mindwm(ast, 0xA0100000) == 0x41424344){
+    reg_04 |= 0x03;
+    reg_14 |= (tRFC >> 24) & 0xFF;
+  /* Check 4Gbit */
+  }else if(ast_mindwm(ast, 0x90100000) == 0x35363738){
+    reg_04 |= 0x02;
+    reg_14 |= (tRFC >> 16) & 0xFF;
+  /* Check 2Gbit */
+  }else if(ast_mindwm(ast, 0x88100000) == 0x292A2B2C){
+    reg_04 |= 0x01;
+    reg_14 |= (tRFC >> 8) & 0xFF;
+  }else{
+    reg_14 |= tRFC & 0xFF;
+  }
+  ast_moutdwm(ast, 0x1E6E0004, reg_04);
+  ast_moutdwm(ast, 0x1E6E0014, reg_14);
+}
+
+static void Enable_Cache(struct ast_private *ast)
+{
+  u32 reg_04, data;
+
+  reg_04 = ast_mindwm(ast, 0x1E6E0004);
+  ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x1000);
+
+  do{
+    data = ast_mindwm(ast, 0x1E6E0004);
+  }while(!(data & 0x80000));
+  ast_moutdwm(ast, 0x1E6E0004, reg_04 | 0x400);
+}
+
+static void Set_MPLL(struct ast_private *ast)
+{
+  u32 addr, data, param;
+
+  /* Reset MMC */
+  ast_moutdwm(ast, 0x1E6E0000,0xFC600309);
+  ast_moutdwm(ast, 0x1E6E0034,0x00020080);
+  for(addr = 0x1e6e0004;addr < 0x1e6e0090;){
+    ast_moutdwm(ast, addr, 0x0);
+    addr += 4;
+  }
+  ast_moutdwm(ast, 0x1E6E0034,0x00020000);
+
+  ast_moutdwm(ast, 0x1E6E2000, 0x1688A8A8);
+  data = ast_mindwm(ast, 0x1E6E2070) & 0x00800000;
+  if(data){                  /* CLKIN = 25MHz */
+    param = 0x930023E0;
+    ast_moutdwm(ast, 0x1E6E2160, 0x00011320);
+  }else{					 /* CLKIN = 24MHz */
+    param = 0x93002400;
+  }
+  ast_moutdwm(ast, 0x1E6E2020, param);
+  udelay(100);
+}
+
+static void Reset_MMC(struct ast_private *ast)
+{
+  ast_moutdwm(ast, 0x1E78505C,0x00000004);
+  ast_moutdwm(ast, 0x1E785044,0x00000001);
+  ast_moutdwm(ast, 0x1E785048,0x00004755);
+  ast_moutdwm(ast, 0x1E78504C,0x00000013);
+  mdelay(100);					/* delay 100ms */
+  ast_moutdwm(ast, 0x1E785054,0x00000077);
+  ast_moutdwm(ast, 0x1E6E0000,0xFC600309);
+}
+
+static void DDR3_Init_AST2500(struct ast_private *ast, u32 *ddr_table)
+{
+
+  ast_moutdwm(ast, 0x1E6E0004,0x00000303);
+  ast_moutdwm(ast, 0x1E6E0010,ddr_table[REGIDX_010]);
+  ast_moutdwm(ast, 0x1E6E0014,ddr_table[REGIDX_014]);
+  ast_moutdwm(ast, 0x1E6E0018,ddr_table[REGIDX_018]);
+  ast_moutdwm(ast, 0x1E6E0020,ddr_table[REGIDX_020]);          /* MODEREG4/6 */
+  ast_moutdwm(ast, 0x1E6E0024,ddr_table[REGIDX_024]);          /* MODEREG5 */
+  ast_moutdwm(ast, 0x1E6E002C,ddr_table[REGIDX_02C] | 0x100);  /* MODEREG0/2 */
+  ast_moutdwm(ast, 0x1E6E0030,ddr_table[REGIDX_030]);          /* MODEREG1/3 */
+
+  /* DDR PHY Setting */
+  ast_moutdwm(ast, 0x1E6E0200,0x02492AAE);
+  ast_moutdwm(ast, 0x1E6E0204,0x00001001);
+  ast_moutdwm(ast, 0x1E6E020C,0x55E00B0B);
+  ast_moutdwm(ast, 0x1E6E0210,0x20000000);
+  ast_moutdwm(ast, 0x1E6E0214,ddr_table[REGIDX_214]);
+  ast_moutdwm(ast, 0x1E6E02E0,ddr_table[REGIDX_2E0]);
+  ast_moutdwm(ast, 0x1E6E02E4,ddr_table[REGIDX_2E4]);
+  ast_moutdwm(ast, 0x1E6E02E8,ddr_table[REGIDX_2E8]);
+  ast_moutdwm(ast, 0x1E6E02EC,ddr_table[REGIDX_2EC]);
+  ast_moutdwm(ast, 0x1E6E02F0,ddr_table[REGIDX_2F0]);
+  ast_moutdwm(ast, 0x1E6E02F4,ddr_table[REGIDX_2F4]);
+  ast_moutdwm(ast, 0x1E6E02F8,ddr_table[REGIDX_2F8]);
+  ast_moutdwm(ast, 0x1E6E0290,0x00100008);
+  ast_moutdwm(ast, 0x1E6E02C0,0x00000006);
+
+  /* Controller Setting */
+  ast_moutdwm(ast, 0x1E6E0034,0x00020091);
+
+  /* Wait DDR PHY init done */
+  Do_DDRPHY_Init(ast);
+
+  ast_moutdwm(ast, 0x1E6E0120,ddr_table[REGIDX_PLL]);
+  ast_moutdwm(ast, 0x1E6E000C,0x42AA5C81);
+  ast_moutdwm(ast, 0x1E6E0034,0x0001AF93);
+
+  Check_DRAM_Size(ast, ddr_table[REGIDX_RFC]);
+  Enable_Cache(ast);
+  ast_moutdwm(ast, 0x1E6E001C,0x00000008);
+  ast_moutdwm(ast, 0x1E6E0038,0xFFFFFF00);
+}
+
+static void DDR4_Init_AST2500(struct ast_private *ast, u32 *ddr_table)
+{
+  u32 data, data2, pass, retrycnt;
+  u32 ddr_vref, phy_vref;
+  u32 min_ddr_vref=0, min_phy_vref=0;
+  u32 max_ddr_vref=0, max_phy_vref=0;
+
+  ast_moutdwm(ast, 0x1E6E0004,0x00000313);
+  ast_moutdwm(ast, 0x1E6E0010,ddr_table[REGIDX_010]);
+  ast_moutdwm(ast, 0x1E6E0014,ddr_table[REGIDX_014]);
+  ast_moutdwm(ast, 0x1E6E0018,ddr_table[REGIDX_018]);
+  ast_moutdwm(ast, 0x1E6E0020,ddr_table[REGIDX_020]);          /* MODEREG4/6 */
+  ast_moutdwm(ast, 0x1E6E0024,ddr_table[REGIDX_024]);          /* MODEREG5 */
+  ast_moutdwm(ast, 0x1E6E002C,ddr_table[REGIDX_02C] | 0x100);  /* MODEREG0/2 */
+  ast_moutdwm(ast, 0x1E6E0030,ddr_table[REGIDX_030]);          /* MODEREG1/3 */
+
+  /* DDR PHY Setting */
+  ast_moutdwm(ast, 0x1E6E0200,0x42492AAE);
+  ast_moutdwm(ast, 0x1E6E0204,0x09002000);
+  ast_moutdwm(ast, 0x1E6E020C,0x55E00B0B);
+  ast_moutdwm(ast, 0x1E6E0210,0x20000000);
+  ast_moutdwm(ast, 0x1E6E0214,ddr_table[REGIDX_214]);
+  ast_moutdwm(ast, 0x1E6E02E0,ddr_table[REGIDX_2E0]);
+  ast_moutdwm(ast, 0x1E6E02E4,ddr_table[REGIDX_2E4]);
+  ast_moutdwm(ast, 0x1E6E02E8,ddr_table[REGIDX_2E8]);
+  ast_moutdwm(ast, 0x1E6E02EC,ddr_table[REGIDX_2EC]);
+  ast_moutdwm(ast, 0x1E6E02F0,ddr_table[REGIDX_2F0]);
+  ast_moutdwm(ast, 0x1E6E02F4,ddr_table[REGIDX_2F4]);
+  ast_moutdwm(ast, 0x1E6E02F8,ddr_table[REGIDX_2F8]);
+  ast_moutdwm(ast, 0x1E6E0290,0x00100008);
+  ast_moutdwm(ast, 0x1E6E02C4,0x3C183C3C);
+  ast_moutdwm(ast, 0x1E6E02C8,0x00631E0E);
+
+  /* Controller Setting */
+  ast_moutdwm(ast, 0x1E6E0034,0x0001A991);
+
+  /* Train PHY Vref first */
+  pass = 0;                                                                                         /* add at V1.1 */
+  for(retrycnt = 0;retrycnt < 4 && pass == 0;retrycnt++){                                           /* add at V1.1 */
+    max_phy_vref = 0x0;
+    pass = 0;
+    ast_moutdwm(ast, 0x1E6E02C0,0x00001C06);
+    for(phy_vref = 0x40;phy_vref < 0x80;phy_vref++){
+      ast_moutdwm(ast, 0x1E6E000C,0x00000000);
+      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
+      ast_moutdwm(ast, 0x1E6E02CC,phy_vref | (phy_vref << 8));
+      /* Fire DFI Init */
+      Do_DDRPHY_Init(ast);
+      ast_moutdwm(ast, 0x1E6E000C,0x00005C01);
+      if(CBRTest_AST2500(ast)){
+        pass++;
+        data = ast_mindwm(ast, 0x1E6E03D0);
+        data2 = data >> 8;
+        data  = data & 0xff;
+        if(data > data2){
+          data = data2;
+        }
+
+        if(max_phy_vref < data){
+          max_phy_vref = data;
+          min_phy_vref = phy_vref;
+        }
+      }else if(pass > 0){
+        break;
+      }
+    }
+  }                                                                                                 /* add at V1.1 */
+  ast_moutdwm(ast, 0x1E6E02CC,min_phy_vref | (min_phy_vref << 8));
+
+  /* Train DDR Vref next */
+  pass = 0;                                                                                         /* add at V1.1 */
+  for(retrycnt = 0;retrycnt < 4 && pass == 0;retrycnt++){                                           /* add at V1.1 */
+    min_ddr_vref = 0xFF;
+    max_ddr_vref = 0x0;
+    pass = 0;
+    for(ddr_vref = 0x00;ddr_vref < 0x40;ddr_vref++){
+      ast_moutdwm(ast, 0x1E6E000C,0x00000000);
+      ast_moutdwm(ast, 0x1E6E0060,0x00000000);
+      ast_moutdwm(ast, 0x1E6E02C0,0x00000006 | (ddr_vref << 8));
+      /* Fire DFI Init */
+      Do_DDRPHY_Init(ast);
+      ast_moutdwm(ast, 0x1E6E000C,0x00005C01);
+      if(CBRTest_AST2500(ast)){
+        pass++;
+        if(min_ddr_vref > ddr_vref){
+          min_ddr_vref = ddr_vref;
+        }
+        if(max_ddr_vref < ddr_vref){
+          max_ddr_vref = ddr_vref;
+        }
+      }else if(pass != 0){
+        break;
+      }
+    }
+  }                                                                                                 /* add at V1.1 */
+  ast_moutdwm(ast, 0x1E6E000C,0x00000000);
+  ast_moutdwm(ast, 0x1E6E0060,0x00000000);
+  ddr_vref = (min_ddr_vref + max_ddr_vref + 1) >> 1;
+  ast_moutdwm(ast, 0x1E6E02C0,0x00000006 | (ddr_vref << 8));
+
+  /* Wait DDR PHY init done */
+  Do_DDRPHY_Init(ast);
+
+  ast_moutdwm(ast, 0x1E6E0120,ddr_table[REGIDX_PLL]);
+  ast_moutdwm(ast, 0x1E6E000C,0x42AA5C81);
+  ast_moutdwm(ast, 0x1E6E0034,0x0001AF93);
+
+  Check_DRAM_Size(ast, ddr_table[REGIDX_RFC]);
+  Enable_Cache(ast);
+  ast_moutdwm(ast, 0x1E6E001C,0x00000008);
+  ast_moutdwm(ast, 0x1E6E0038,0xFFFFFF00);
+}
+
+static u32 DRAM_Init_AST2500(struct ast_private *ast)
+{
+  u32 data;
+
+START_INIT:
+  Set_MPLL(ast);
+  Reset_MMC(ast);
+  DDR_Init_Common(ast);
+  data = ast_mindwm(ast, 0x1E6E2070);
+  if(data & 0x01000000){
+    DDR4_Init_AST2500(ast, ddr4_1600_timing_table);
+  }else{
+    DDR3_Init_AST2500(ast, ddr3_1600_timing_table);
+  }
+  if(!DDRTest_AST2500(ast)){                                                                      /* add at V1.1 */
+    goto START_INIT;                                                                              /* add at V1.1 */
+  }
+  ast_moutdwm(ast, 0x1E6E2040, ast_mindwm(ast, 0x1E6E2040) | 0x41);
+  /* Patch code */
+  data = ast_mindwm(ast, 0x1E6E200C) & 0xF9FFFFFF;
+  ast_moutdwm(ast, 0x1E6E200C, data | 0x10000000);
+  return(1);
+}
+
+static void ast_init_dram_2500(struct drm_device *dev)
+{
+	struct ast_private *ast = dev->dev_private;
+	u32 temp;
+	u8 reg;
+
+	reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
+	if ((reg & 0x80) == 0) {/* vga only */
+  		/************************************************************************************************/
+  		/* Below patch should be executed at the first time before any access to AST25xx                */
+  		/* Clear bus lock condition */
+  		ast_moutdwm(ast, 0x1e600000,0xAEED1A03);                                                         /* add at V1.1 */
+  		ast_moutdwm(ast, 0x1e600084,0x00010000);                                                         /* add at V1.1 */
+  		ast_moutdwm(ast, 0x1e600088,0x00000000);                                                         /* add at V1.1 */
+  		ast_moutdwm(ast, 0x1e6e2000,0x1688A8A8);                                                         /* add at V1.1 */
+  		/************************************************************************************************/
+
+		ast_write32(ast, 0xf004, 0x1e6e0000);
+		ast_write32(ast, 0xf000, 0x1);
+		ast_write32(ast, 0x12000, 0x1688a8a8);
+		do {
+			;
+		} while (ast_read32(ast, 0x12000) != 0x1);
+
+		ast_write32(ast, 0x10000, 0xfc600309);
+		do {
+			;
+		} while (ast_read32(ast, 0x10000) != 0x1);
+
+		/* Slow down CPU/AHB CLK in VGA only mode */
+		temp = ast_read32(ast, 0x12008);
+		temp |= 0x73;
+		ast_write32(ast, 0x12008, temp);
+
+		/* Reset USB port to patch USB unknown device issue */
+ 	 	ast_moutdwm(ast, 0x1e6e2090, 0x20000000);
+      	temp  = ast_mindwm(ast, 0x1e6e2094);
+      	temp |= 0x00004000;
+      	ast_moutdwm(ast, 0x1e6e2094, temp);
+      	temp  = ast_mindwm(ast, 0x1e6e2070);
+		if (temp & 0x00800000)
+		{
+      		ast_moutdwm(ast, 0x1e6e207c, 0x00800000);
+			mdelay(100);							/* delay 100ms */
+      		ast_moutdwm(ast, 0x1e6e2070, 0x00800000);
+		}
+
+		DRAM_Init_AST2500(ast);
+
+		temp = ast_mindwm(ast, 0x1e6e2040);
+		ast_moutdwm(ast, 0x1e6e2040, temp | 0x40);
+	}
+
+	/* wait ready */
+	do {
+		reg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
+	} while ((reg & 0x40) == 0);
+}
diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h
index 3608d5a..24da4c2 100644
--- a/drivers/gpu/drm/ast/ast_tables.h
+++ b/drivers/gpu/drm/ast/ast_tables.h
@@ -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 @@ 
 	{0x3b, 0x2c, 0x81},					/* 1A: VCLK118_25	*/
 };
 
+static 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 struct ast_vbios_stdtable vbios_stdtable[] = {
 	/* MD_2_3_400 */
 	{
@@ -244,32 +275,32 @@ 
 /* 16:9 */
 static 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 },
+	 (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo | AST2500PreCatchCRT), 60, 1, 0x39 },
 	{1792, 1360, 64,112, 795,  768, 3, 6, VCLK85_5,	         /* end */
 	 (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 1, 0x39 },
 };
 
 static 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 },
-	{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 */
-	 (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 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 */
+     (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 0xFF, 2, 0x3A },
 };
 
 static 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 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 +310,7 @@ 
 
 static 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 +319,7 @@ 
 
 static 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 +328,9 @@ 
 
 static 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