u32 i, data;
        u32 boot_address;
 
+       if (ast->config_mode != ast_use_p2a)
+               return false;
+
        data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
        if (data) {
                boot_address = get_fw_base(ast);
        u8 *fw_addr = NULL;
        u8 jreg;
 
+       if (ast->config_mode != ast_use_p2a)
+               return false;
+
        data = ast_mindwm(ast, 0x1e6e2100) & 0x01;
        if (!data) {
 
        struct ast_private *ast = to_ast_private(dev);
        u32 boot_address, offset, data;
        u8 linkcap[4], linkrate, linklanes, maxclk = 0xff;
+       u32 *plinkcap;
 
-       boot_address = get_fw_base(ast);
-
-       /* validate FW version */
-       offset = 0xf000;
-       data = ast_mindwm(ast, boot_address + offset);
-       if ((data & 0xf0) != 0x10) /* version: 1x */
-               return maxclk;
-
-       /* Read Link Capability */
-       offset  = 0xf014;
-       *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset);
-       if (linkcap[2] == 0) {
-               linkrate = linkcap[0];
-               linklanes = linkcap[1];
-               data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
-               if (data > 0xff)
-                       data = 0xff;
-               maxclk = (u8)data;
+       if (ast->config_mode == ast_use_p2a) {
+               boot_address = get_fw_base(ast);
+
+               /* validate FW version */
+               offset = AST_DP501_GBL_VERSION;
+               data = ast_mindwm(ast, boot_address + offset);
+               if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */
+                       return maxclk;
+
+               /* Read Link Capability */
+               offset  = AST_DP501_LINKRATE;
+               plinkcap = (u32 *)linkcap;
+               *plinkcap  = ast_mindwm(ast, boot_address + offset);
+               if (linkcap[2] == 0) {
+                       linkrate = linkcap[0];
+                       linklanes = linkcap[1];
+                       data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
+                       if (data > 0xff)
+                               data = 0xff;
+                       maxclk = (u8)data;
+               }
+       } else {
+               if (!ast->dp501_fw_buf)
+                       return AST_DP501_DEFAULT_DCLK;  /* 1024x768 as default */
+
+               /* dummy read */
+               offset = 0x0000;
+               data = readl(ast->dp501_fw_buf + offset);
+
+               /* validate FW version */
+               offset = AST_DP501_GBL_VERSION;
+               data = readl(ast->dp501_fw_buf + offset);
+               if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */
+                       return maxclk;
+
+               /* Read Link Capability */
+               offset = AST_DP501_LINKRATE;
+               plinkcap = (u32 *)linkcap;
+               *plinkcap = readl(ast->dp501_fw_buf + offset);
+               if (linkcap[2] == 0) {
+                       linkrate = linkcap[0];
+                       linklanes = linkcap[1];
+                       data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes);
+                       if (data > 0xff)
+                               data = 0xff;
+                       maxclk = (u8)data;
+               }
        }
        return maxclk;
 }
 {
        struct ast_private *ast = to_ast_private(dev);
        u32 i, boot_address, offset, data;
+       u32 *pEDIDidx;
 
-       boot_address = get_fw_base(ast);
-
-       /* validate FW version */
-       offset = 0xf000;
-       data = ast_mindwm(ast, boot_address + offset);
-       if ((data & 0xf0) != 0x10)
-               return false;
-
-       /* validate PnP Monitor */
-       offset = 0xf010;
-       data = ast_mindwm(ast, boot_address + offset);
-       if (!(data & 0x01))
-               return false;
+       if (ast->config_mode == ast_use_p2a) {
+               boot_address = get_fw_base(ast);
 
-       /* Read EDID */
-       offset = 0xf020;
-       for (i = 0; i < 128; i += 4) {
-               data = ast_mindwm(ast, boot_address + offset + i);
-               *(u32 *)(ediddata + i) = data;
+               /* validate FW version */
+               offset = AST_DP501_GBL_VERSION;
+               data = ast_mindwm(ast, boot_address + offset);
+               if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
+                       return false;
+
+               /* validate PnP Monitor */
+               offset = AST_DP501_PNPMONITOR;
+               data = ast_mindwm(ast, boot_address + offset);
+               if (!(data & AST_DP501_PNP_CONNECTED))
+                       return false;
+
+               /* Read EDID */
+               offset = AST_DP501_EDID_DATA;
+               for (i = 0; i < 128; i += 4) {
+                       data = ast_mindwm(ast, boot_address + offset + i);
+                       pEDIDidx = (u32 *)(ediddata + i);
+                       *pEDIDidx = data;
+               }
+       } else {
+               if (!ast->dp501_fw_buf)
+                       return false;
+
+               /* dummy read */
+               offset = 0x0000;
+               data = readl(ast->dp501_fw_buf + offset);
+
+               /* validate FW version */
+               offset = AST_DP501_GBL_VERSION;
+               data = readl(ast->dp501_fw_buf + offset);
+               if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1)
+                       return false;
+
+               /* validate PnP Monitor */
+               offset = AST_DP501_PNPMONITOR;
+               data = readl(ast->dp501_fw_buf + offset);
+               if (!(data & AST_DP501_PNP_CONNECTED))
+                       return false;
+
+               /* Read EDID */
+               offset = AST_DP501_EDID_DATA;
+               for (i = 0; i < 128; i += 4) {
+                       data = readl(ast->dp501_fw_buf + offset + i);
+                       pEDIDidx = (u32 *)(ediddata + i);
+                       *pEDIDidx = data;
+               }
        }
 
        return true;
 
        if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
                /* Double check it's actually working */
                data = ast_read32(ast, 0xf004);
-               if (data != 0xFFFFFFFF) {
+               if ((data != 0xFFFFFFFF) && (data != 0x00)) {
                        /* P2A works, grab silicon revision */
                        ast->config_mode = ast_use_p2a;
 
                return ast;
        dev = &ast->base;
 
+       dev->pdev = pdev;
        pci_set_drvdata(pdev, dev);
 
        ast->regs = pcim_iomap(pdev, 1, 0);
        if (ret)
                return ERR_PTR(ret);
 
+       /* map reserved buffer */
+       ast->dp501_fw_buf = NULL;
+       if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) {
+               ast->dp501_fw_buf = pci_iomap_range(dev->pdev, 0, dev->vram_mm->vram_size, 0);
+               if (!ast->dp501_fw_buf)
+                       drm_info(dev, "failed to map reserved buffer!\n");
+       }
+
        ret = ast_mode_config_init(ast);
        if (ret)
                return ERR_PTR(ret);