#include "ast_drv.h"
 #include "ast_vbios.h"
 
+static int ast_astdp_get_mode_index(const struct ast_vbios_enhtable *vmode)
+{
+       u8 refresh_rate_index;
+
+       if (vmode->refresh_rate_index < 1 || vmode->refresh_rate_index > 255)
+               return -EINVAL;
+
+       refresh_rate_index = vmode->refresh_rate_index - 1;
+
+       switch (vmode->hde) {
+       case 320:
+               if (vmode->vde == 240)
+                       return ASTDP_320x240_60;
+               break;
+       case 400:
+               if (vmode->vde == 300)
+                       return ASTDP_400x300_60;
+               break;
+       case 512:
+               if (vmode->vde == 384)
+                       return ASTDP_512x384_60;
+               break;
+       case 640:
+               if (vmode->vde == 480)
+                       return (u8)(ASTDP_640x480_60 + (u8)refresh_rate_index);
+               break;
+       case 800:
+               if (vmode->vde == 600)
+                       return (u8)(ASTDP_800x600_56 + (u8)refresh_rate_index);
+               break;
+       case 1024:
+               if (vmode->vde == 768)
+                       return (u8)(ASTDP_1024x768_60 + (u8)refresh_rate_index);
+               break;
+       case 1152:
+               if (vmode->vde == 864)
+                       return ASTDP_1152x864_75;
+               break;
+       case 1280:
+               if (vmode->vde == 800)
+                       return (u8)(ASTDP_1280x800_60_RB - (u8)refresh_rate_index);
+               if (vmode->vde == 1024)
+                       return (u8)(ASTDP_1280x1024_60 + (u8)refresh_rate_index);
+               break;
+       case 1360:
+       case 1366:
+               if (vmode->vde == 768)
+                       return ASTDP_1366x768_60;
+               break;
+       case 1440:
+               if (vmode->vde == 900)
+                       return (u8)(ASTDP_1440x900_60_RB - (u8)refresh_rate_index);
+               break;
+       case 1600:
+               if (vmode->vde == 900)
+                       return (u8)(ASTDP_1600x900_60_RB - (u8)refresh_rate_index);
+               if (vmode->vde == 1200)
+                       return ASTDP_1600x1200_60;
+               break;
+       case 1680:
+               if (vmode->vde == 1050)
+                       return (u8)(ASTDP_1680x1050_60_RB - (u8)refresh_rate_index);
+               break;
+       case 1920:
+               if (vmode->vde == 1080)
+                       return ASTDP_1920x1080_60;
+               if (vmode->vde == 1200)
+                       return ASTDP_1920x1200_60;
+               break;
+       default:
+               break;
+       }
+
+       return -EINVAL;
+}
+
 static bool ast_astdp_is_connected(struct ast_device *ast)
 {
        if (!ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xDF, AST_IO_VGACRDF_HPD))
        drm_WARN_ON(dev, !__ast_dp_wait_enable(ast, enabled));
 }
 
-static void ast_dp_set_mode(struct drm_crtc *crtc, struct ast_vbios_mode_info *vbios_mode)
-{
-       struct ast_device *ast = to_ast_device(crtc->dev);
-
-       u32 ulRefreshRateIndex;
-       u8 ModeIdx;
-
-       ulRefreshRateIndex = vbios_mode->enh_table->refresh_rate_index - 1;
-
-       switch (crtc->mode.crtc_hdisplay) {
-       case 320:
-               ModeIdx = ASTDP_320x240_60;
-               break;
-       case 400:
-               ModeIdx = ASTDP_400x300_60;
-               break;
-       case 512:
-               ModeIdx = ASTDP_512x384_60;
-               break;
-       case 640:
-               ModeIdx = (ASTDP_640x480_60 + (u8) ulRefreshRateIndex);
-               break;
-       case 800:
-               ModeIdx = (ASTDP_800x600_56 + (u8) ulRefreshRateIndex);
-               break;
-       case 1024:
-               ModeIdx = (ASTDP_1024x768_60 + (u8) ulRefreshRateIndex);
-               break;
-       case 1152:
-               ModeIdx = ASTDP_1152x864_75;
-               break;
-       case 1280:
-               if (crtc->mode.crtc_vdisplay == 800)
-                       ModeIdx = (ASTDP_1280x800_60_RB - (u8) ulRefreshRateIndex);
-               else            // 1024
-                       ModeIdx = (ASTDP_1280x1024_60 + (u8) ulRefreshRateIndex);
-               break;
-       case 1360:
-       case 1366:
-               ModeIdx = ASTDP_1366x768_60;
-               break;
-       case 1440:
-               ModeIdx = (ASTDP_1440x900_60_RB - (u8) ulRefreshRateIndex);
-               break;
-       case 1600:
-               if (crtc->mode.crtc_vdisplay == 900)
-                       ModeIdx = (ASTDP_1600x900_60_RB - (u8) ulRefreshRateIndex);
-               else            //1200
-                       ModeIdx = ASTDP_1600x1200_60;
-               break;
-       case 1680:
-               ModeIdx = (ASTDP_1680x1050_60_RB - (u8) ulRefreshRateIndex);
-               break;
-       case 1920:
-               if (crtc->mode.crtc_vdisplay == 1080)
-                       ModeIdx = ASTDP_1920x1080_60;
-               else            //1200
-                       ModeIdx = ASTDP_1920x1200_60;
-               break;
-       default:
-               return;
-       }
-
-       /*
-        * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
-        * CRE1[7:0]: MISC1 (default: 0x00)
-        * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
-        */
-       ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE0, ASTDP_AND_CLEAR_MASK,
-                              ASTDP_MISC0_24bpp);
-       ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE1, ASTDP_AND_CLEAR_MASK, ASTDP_MISC1);
-       ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE2, ASTDP_AND_CLEAR_MASK, ModeIdx);
-}
-
 static void ast_wait_for_vretrace(struct ast_device *ast)
 {
        unsigned long timeout = jiffies + HZ;
                                                     struct drm_crtc_state *crtc_state,
                                                     struct drm_connector_state *conn_state)
 {
-       struct drm_crtc *crtc = crtc_state->crtc;
+       struct drm_device *dev = encoder->dev;
+       struct ast_device *ast = to_ast_device(dev);
        struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
        struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
+       int mode_index;
+       u8 vgacre0, vgacre1, vgacre2;
+
+       mode_index = ast_astdp_get_mode_index(vbios_mode_info->enh_table);
+       if (drm_WARN_ON(dev, mode_index < 0))
+               return;
+
+       /*
+        * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
+        * CRE1[7:0]: MISC1 (default: 0x00)
+        * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
+        */
+       vgacre0 = AST_IO_VGACRE0_24BPP;
+       vgacre1 = 0x00;
+       vgacre2 = mode_index & 0xff;
 
-       ast_dp_set_mode(crtc, vbios_mode_info);
+       ast_set_index_reg(ast, AST_IO_VGACRI, 0xe0, vgacre0);
+       ast_set_index_reg(ast, AST_IO_VGACRI, 0xe1, vgacre1);
+       ast_set_index_reg(ast, AST_IO_VGACRI, 0xe2, vgacre2);
 }
 
 static void ast_astdp_encoder_helper_atomic_enable(struct drm_encoder *encoder,
 
 #define AST_IO_VGACRD1_TX_ASTDP                        0x0e
 #define AST_IO_VGACRD1_SUPPORTS_WUXGA          BIT(0)
 
+/*
+ * AST DisplayPort
+ */
 #define AST_IO_VGACRD7_EDID_VALID_FLAG BIT(0)
 #define AST_IO_VGACRDC_LINK_SUCCESS    BIT(0)
 #define AST_IO_VGACRDF_HPD             BIT(0)
 #define AST_IO_VGACRDF_DP_VIDEO_ENABLE BIT(4) /* mirrors AST_IO_VGACRE3_DP_VIDEO_ENABLE */
+#define AST_IO_VGACRE0_24BPP           BIT(5) /* 18 bpp, if unset  */
 #define AST_IO_VGACRE3_DP_VIDEO_ENABLE BIT(0)
 #define AST_IO_VGACRE3_DP_PHY_SLEEP    BIT(4)
 #define AST_IO_VGACRE5_EDID_READ_DONE  BIT(0)
 #define AST_IO_VGAIR1_R                        (0x5A)
 #define AST_IO_VGAIR1_VREFRESH         BIT(3)
 
-/*
- * AST DisplayPort
- */
-
-/*
- * ASTDP setmode registers:
- * CRE0[7:0]: MISC0 ((0x00: 18-bpp) or (0x20: 24-bpp)
- * CRE1[7:0]: MISC1 (default: 0x00)
- * CRE2[7:0]: video format index (0x00 ~ 0x20 or 0x40 ~ 0x50)
- */
-#define ASTDP_MISC0_24bpp              BIT(5)
-#define ASTDP_MISC1                    0
-#define ASTDP_AND_CLEAR_MASK           0x00
-
 #endif