drm/ast: Add helpers for VBIOS mode lookup
authorThomas Zimmermann <tzimmermann@suse.de>
Fri, 31 Jan 2025 09:21:10 +0000 (10:21 +0100)
committerThomas Zimmermann <tzimmermann@suse.de>
Mon, 3 Feb 2025 13:01:12 +0000 (14:01 +0100)
Mode lines are independent from hardware Gen or TX chip, so hide all
VBIOS mode tables in ast_vbios.c.

Move the look-up code for VBIOS modes from ast_vbios_get_mode_info()
to ast_vbios_find_mode(). The new look-up function respects the
supported-mode flags in struct ast_device. For example, if a device
does not have struct ast_device.support_fullhd set, the helper does
not return a valid mode for 1920x1080. Taking the supported-mode flags
into account allows for making the VBIOS tables the single reference
for validating and setting display modes against hardware capabilities.

v2:
- replace mode switch with look-up table (Jocelyn)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20250131092257.115596-11-tzimmermann@suse.de
drivers/gpu/drm/ast/Makefile
drivers/gpu/drm/ast/ast_dp.c
drivers/gpu/drm/ast/ast_drv.h
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/ast/ast_tables.h
drivers/gpu/drm/ast/ast_vbios.c [new file with mode: 0644]
drivers/gpu/drm/ast/ast_vbios.h [new file with mode: 0644]

index 47da848fa3fc1d1164010d0968b3cff9264eb2a4..3107ea9c7bf55811f048a7cb3d6b4ba7510f4b19 100644 (file)
@@ -13,6 +13,7 @@ ast-y := \
        ast_mode.o \
        ast_post.o \
        ast_sil164.o \
+       ast_vbios.o \
        ast_vga.o
 
 obj-$(CONFIG_DRM_AST) := ast.o
index 30aad5c0112a155576c860fb2a64c2e631420f21..eb65c0881fa78148819133d2f75ba1da3c963d98 100644 (file)
@@ -12,6 +12,7 @@
 #include <drm/drm_probe_helper.h>
 
 #include "ast_drv.h"
+#include "ast_vbios.h"
 
 static bool ast_astdp_is_connected(struct ast_device *ast)
 {
index 4e3a88f8a85ca78cdfc4e638fe0708c66808e460..9309cc5e81b0f730db013763e1527b345f9e5239 100644 (file)
@@ -39,6 +39,8 @@
 
 #include "ast_reg.h"
 
+struct ast_vbios_enhtable;
+
 #define DRIVER_AUTHOR          "Dave Airlie"
 
 #define DRIVER_NAME            "ast"
@@ -350,22 +352,6 @@ struct ast_vbios_stdtable {
        u8 gr[9];
 };
 
-struct ast_vbios_enhtable {
-       u32 ht;
-       u32 hde;
-       u32 hfp;
-       u32 hsync;
-       u32 vt;
-       u32 vde;
-       u32 vfp;
-       u32 vsync;
-       u32 dclk_index;
-       u32 flags;
-       u32 refresh_rate;
-       u32 refresh_rate_index;
-       u32 mode_id;
-};
-
 struct ast_vbios_dclk_info {
        u8 param1;
        u8 param2;
index 3f437f871a357a724d765844a1cf479ded0eb264..14c0c281a6834f86db59ba0a8f7e417acd722071 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "ast_drv.h"
 #include "ast_tables.h"
+#include "ast_vbios.h"
 
 #define AST_LUT_SIZE 256
 
@@ -106,14 +107,12 @@ static void ast_crtc_set_gamma(struct ast_device *ast,
        }
 }
 
-static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
+static bool ast_get_vbios_mode_info(struct ast_device *ast,
+                                   const struct drm_format_info *format,
                                    const struct drm_display_mode *mode,
                                    struct drm_display_mode *adjusted_mode,
                                    struct ast_vbios_mode_info *vbios_mode)
 {
-       u32 refresh_rate_index = 0, refresh_rate;
-       const struct ast_vbios_enhtable *best = NULL;
-       const struct ast_vbios_enhtable *loop;
        u32 hborder, vborder;
 
        switch (format->cpp[0] * 8) {
@@ -131,73 +130,10 @@ static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
                return false;
        }
 
-       switch (mode->hdisplay) {
-       case 640:
-               vbios_mode->enh_table = &res_640x480[refresh_rate_index];
-               break;
-       case 800:
-               vbios_mode->enh_table = &res_800x600[refresh_rate_index];
-               break;
-       case 1024:
-               vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
-               break;
-       case 1152:
-               vbios_mode->enh_table = &res_1152x864[refresh_rate_index];
-               break;
-       case 1280:
-               if (mode->vdisplay == 800)
-                       vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
-               else
-                       vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
-               break;
-       case 1360:
-               vbios_mode->enh_table = &res_1360x768[refresh_rate_index];
-               break;
-       case 1440:
-               vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
-               break;
-       case 1600:
-               if (mode->vdisplay == 900)
-                       vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
-               else
-                       vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
-               break;
-       case 1680:
-               vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
-               break;
-       case 1920:
-               if (mode->vdisplay == 1080)
-                       vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
-               else
-                       vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
-               break;
-       default:
-               return false;
-       }
-
-       refresh_rate = drm_mode_vrefresh(mode);
-
-       loop = vbios_mode->enh_table;
-
-       while (ast_vbios_mode_is_valid(loop)) {
-               if (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (loop->flags & PVSync))  ||
-                   ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (loop->flags & NVSync))  ||
-                   ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (loop->flags & PHSync))  ||
-                   ((mode->flags & DRM_MODE_FLAG_PHSYNC) && (loop->flags & NHSync))) {
-                       loop++;
-                       continue;
-               }
-               if (loop->refresh_rate <= refresh_rate &&
-                   (!best || loop->refresh_rate > best->refresh_rate))
-                       best = loop;
-               loop++;
-       }
-
-       if (!best)
+       vbios_mode->enh_table = ast_vbios_find_mode(ast, mode);
+       if (!vbios_mode->enh_table)
                return false;
 
-       vbios_mode->enh_table = best;
-
        hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
        vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;
 
@@ -1109,6 +1045,7 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
        struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
        struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
        struct drm_device *dev = crtc->dev;
+       struct ast_device *ast = to_ast_device(dev);
        struct ast_crtc_state *ast_state;
        const struct drm_format_info *format;
        bool succ;
@@ -1143,7 +1080,7 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
                }
        }
 
-       succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
+       succ = ast_get_vbios_mode_info(ast, format, &crtc_state->mode,
                                       &crtc_state->adjusted_mode,
                                       &ast_state->vbios_mode_info);
        if (!succ)
index 4367817b2f80639ce448bab02afd1c9c33510fc2..f1c9f7e1f1fcde19f6eae78035a429f79d49cdbb 100644 (file)
 #define HiCModeIndex           3
 #define TrueCModeIndex         4
 
-#define Charx8Dot               0x00000001
-#define HalfDCLK                0x00000002
-#define DoubleScanMode          0x00000004
-#define LineCompareOff          0x00000008
-#define HBorder                 0x00000020
-#define VBorder                 0x00000010
-#define WideScreenMode         0x00000100
-#define NewModeInfo            0x00000200
-#define NHSync                 0x00000400
-#define PHSync                 0x00000800
-#define NVSync                 0x00001000
-#define PVSync                 0x00002000
-#define SyncPP                 (PVSync | PHSync)
-#define SyncPN                 (PVSync | NHSync)
-#define SyncNP                 (NVSync | PHSync)
-#define SyncNN                 (NVSync | NHSync)
-#define AST2500PreCatchCRT             0x00004000
-
-/* DCLK Index */
-#define VCLK25_175                     0x00
-#define VCLK28_322                     0x01
-#define VCLK31_5                       0x02
-#define VCLK36                         0x03
-#define VCLK40                         0x04
-#define VCLK49_5                       0x05
-#define VCLK50                         0x06
-#define VCLK56_25                      0x07
-#define VCLK65                 0x08
-#define VCLK75                 0x09
-#define VCLK78_75                      0x0A
-#define VCLK94_5                       0x0B
-#define VCLK108                        0x0C
-#define VCLK135                        0x0D
-#define VCLK157_5                      0x0E
-#define VCLK162                        0x0F
-/* #define VCLK193_25                  0x10 */
-#define VCLK154                0x10
-#define VCLK83_5               0x11
-#define VCLK106_5              0x12
-#define VCLK146_25             0x13
-#define VCLK148_5              0x14
-#define VCLK71                 0x15
-#define VCLK88_75              0x16
-#define VCLK119                0x17
-#define VCLK85_5               0x18
-#define VCLK97_75              0x19
-#define VCLK118_25                     0x1A
-
 static const struct ast_vbios_dclk_info dclk_table[] = {
        {0x2C, 0xE7, 0x03},                     /* 00: VCLK25_175       */
        {0x95, 0x62, 0x03},                     /* 01: VCLK28_322       */
@@ -214,133 +166,4 @@ static const struct ast_vbios_stdtable vbios_stdtable[] = {
        },
 };
 
-#define AST_VBIOS_INVALID_MODE \
-       {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}
-
-static inline bool ast_vbios_mode_is_valid(const struct ast_vbios_enhtable *vmode)
-{
-       return vmode->ht && vmode->vt && vmode->refresh_rate;
-}
-
-static const struct ast_vbios_enhtable res_640x480[] = {
-       { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175,  /* 60Hz */
-         (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2E },
-       { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5,   /* 72Hz */
-         (SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2E  },
-       { 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5,   /* 75Hz */
-         (SyncNN | Charx8Dot) , 75, 3, 0x2E },
-       { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36,     /* 85Hz */
-         (SyncNN | Charx8Dot) , 85, 4, 0x2E },
-       AST_VBIOS_INVALID_MODE,                         /* end */
-};
-
-static const struct ast_vbios_enhtable res_800x600[] = {
-       {1024, 800, 24, 72, 625, 600, 1, 2, VCLK36,     /* 56Hz */
-        (SyncPP | Charx8Dot), 56, 1, 0x30 },
-       {1056, 800, 40, 128, 628, 600, 1, 4, VCLK40,    /* 60Hz */
-        (SyncPP | Charx8Dot), 60, 2, 0x30 },
-       {1040, 800, 56, 120, 666, 600, 37, 6, VCLK50,   /* 72Hz */
-        (SyncPP | Charx8Dot), 72, 3, 0x30 },
-       {1056, 800, 16, 80, 625, 600, 1, 3, VCLK49_5,   /* 75Hz */
-        (SyncPP | Charx8Dot), 75, 4, 0x30 },
-       {1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25,  /* 85Hz */
-        (SyncPP | Charx8Dot), 84, 5, 0x30 },
-       AST_VBIOS_INVALID_MODE,                         /* end */
-};
-
-
-static const struct ast_vbios_enhtable res_1024x768[] = {
-       {1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65,   /* 60Hz */
-        (SyncNN | Charx8Dot), 60, 1, 0x31 },
-       {1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75,   /* 70Hz */
-        (SyncNN | Charx8Dot), 70, 2, 0x31 },
-       {1312, 1024, 16, 96, 800, 768, 1, 3, VCLK78_75, /* 75Hz */
-        (SyncPP | Charx8Dot), 75, 3, 0x31 },
-       {1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5,  /* 85Hz */
-        (SyncPP | Charx8Dot), 84, 4, 0x31 },
-       AST_VBIOS_INVALID_MODE,                         /* end */
-};
-
-static const struct ast_vbios_enhtable res_1280x1024[] = {
-       {1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108,        /* 60Hz */
-        (SyncPP | Charx8Dot), 60, 1, 0x32 },
-       {1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135,        /* 75Hz */
-        (SyncPP | Charx8Dot), 75, 2, 0x32 },
-       {1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5,      /* 85Hz */
-        (SyncPP | Charx8Dot), 85, 3, 0x32 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-static const struct ast_vbios_enhtable res_1600x1200[] = {
-       {2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162,        /* 60Hz */
-        (SyncPP | Charx8Dot), 60, 1, 0x33 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-static const struct ast_vbios_enhtable res_1152x864[] = {
-       {1600, 1152, 64, 128,  900,  864, 1, 3, VCLK108,        /* 75Hz */
-        (SyncPP | Charx8Dot | NewModeInfo), 75, 1, 0x3B },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-/* 16:9 */
-static const struct ast_vbios_enhtable res_1360x768[] = {
-       {1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5,         /* 60Hz */
-        (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-static const struct ast_vbios_enhtable res_1600x900[] = {
-       {1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75,         /* 60Hz CVT RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
-         AST2500PreCatchCRT), 60, 1, 0x3A },
-       {2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25,       /* 60Hz CVT */
-        (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3A },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-static const struct ast_vbios_enhtable res_1920x1080[] = {
-       {2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,       /* 60Hz */
-        (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
-         AST2500PreCatchCRT), 60, 1, 0x38 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-
-/* 16:10 */
-static const struct ast_vbios_enhtable res_1280x800[] = {
-       {1440, 1280, 48, 32,  823,  800, 3, 6, VCLK71,          /* 60Hz RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
-         AST2500PreCatchCRT), 60, 1, 0x35 },
-       {1680, 1280, 72,128,  831,  800, 3, 6, VCLK83_5,        /* 60Hz */
-        (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-
-};
-
-static const struct ast_vbios_enhtable res_1440x900[] = {
-       {1600, 1440, 48, 32,  926,  900, 3, 6, VCLK88_75,       /* 60Hz RB */
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
-         AST2500PreCatchCRT), 60, 1, 0x36 },
-       {1904, 1440, 80,152,  934,  900, 3, 6, VCLK106_5,       /* 60Hz */
-        (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-static const struct ast_vbios_enhtable res_1680x1050[] = {
-       {1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119,         /* 60Hz RB */
-        (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 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
-static const struct ast_vbios_enhtable res_1920x1200[] = {
-       {2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154,         /* 60Hz RB*/
-        (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
-         AST2500PreCatchCRT), 60, 1, 0x34 },
-       AST_VBIOS_INVALID_MODE,                                 /* end */
-};
-
 #endif
diff --git a/drivers/gpu/drm/ast/ast_vbios.c b/drivers/gpu/drm/ast/ast_vbios.c
new file mode 100644 (file)
index 0000000..0953e6d
--- /dev/null
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright (c) 2005 ASPEED Technology Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  The authors makes no representations
+ * about the suitability of this software for any purpose.  It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ast_drv.h"
+#include "ast_vbios.h"
+
+/* 4:3 */
+
+static const struct ast_vbios_enhtable res_640x480[] = {
+       { 800, 640, 8, 96, 525, 480, 2, 2, VCLK25_175,          /* 60 Hz */
+         (SyncNN | HBorder | VBorder | Charx8Dot), 60, 1, 0x2e },
+       { 832, 640, 16, 40, 520, 480, 1, 3, VCLK31_5,           /* 72 Hz */
+         (SyncNN | HBorder | VBorder | Charx8Dot), 72, 2, 0x2e  },
+       { 840, 640, 16, 64, 500, 480, 1, 3, VCLK31_5,           /* 75 Hz */
+         (SyncNN | Charx8Dot), 75, 3, 0x2e },
+       { 832, 640, 56, 56, 509, 480, 1, 3, VCLK36,             /* 85 Hz */
+         (SyncNN | Charx8Dot), 85, 4, 0x2e },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_800x600[] = {
+       { 1024, 800, 24, 72, 625, 600, 1, 2, VCLK36,            /* 56 Hz */
+         (SyncPP | Charx8Dot), 56, 1, 0x30 },
+       { 1056, 800, 40, 128, 628, 600, 1, 4, VCLK40,           /* 60 Hz */
+         (SyncPP | Charx8Dot), 60, 2, 0x30 },
+       { 1040, 800, 56, 120, 666, 600, 37, 6, VCLK50,          /* 72 Hz */
+         (SyncPP | Charx8Dot), 72, 3, 0x30 },
+       { 1056, 800, 16, 80, 625, 600, 1, 3, VCLK49_5,          /* 75 Hz */
+         (SyncPP | Charx8Dot), 75, 4, 0x30 },
+       { 1048, 800, 32, 64, 631, 600, 1, 3, VCLK56_25,         /* 85 Hz */
+         (SyncPP | Charx8Dot), 84, 5, 0x30 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1024x768[] = {
+       { 1344, 1024, 24, 136, 806, 768, 3, 6, VCLK65,          /* 60 Hz */
+         (SyncNN | Charx8Dot), 60, 1, 0x31 },
+       { 1328, 1024, 24, 136, 806, 768, 3, 6, VCLK75,          /* 70 Hz */
+         (SyncNN | Charx8Dot), 70, 2, 0x31 },
+       { 1312, 1024, 16, 96, 800, 768, 1, 3, VCLK78_75,        /* 75 Hz */
+         (SyncPP | Charx8Dot), 75, 3, 0x31 },
+       { 1376, 1024, 48, 96, 808, 768, 1, 3, VCLK94_5,         /* 85 Hz */
+         (SyncPP | Charx8Dot), 84, 4, 0x31 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1152x864[] = {
+       { 1600, 1152, 64, 128,  900,  864, 1, 3, VCLK108,       /* 75 Hz */
+         (SyncPP | Charx8Dot | NewModeInfo), 75, 1, 0x3b },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1280x1024[] = {
+       { 1688, 1280, 48, 112, 1066, 1024, 1, 3, VCLK108,       /* 60 Hz */
+         (SyncPP | Charx8Dot), 60, 1, 0x32 },
+       { 1688, 1280, 16, 144, 1066, 1024, 1, 3, VCLK135,       /* 75 Hz */
+         (SyncPP | Charx8Dot), 75, 2, 0x32 },
+       { 1728, 1280, 64, 160, 1072, 1024, 1, 3, VCLK157_5,     /* 85 Hz */
+         (SyncPP | Charx8Dot), 85, 3, 0x32 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1600x1200[] = {
+       { 2160, 1600, 64, 192, 1250, 1200, 1, 3, VCLK162,       /* 60 Hz */
+         (SyncPP | Charx8Dot), 60, 1, 0x33 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+/* 16:9 */
+
+static const struct ast_vbios_enhtable res_1360x768[] = {
+       { 1792, 1360, 64, 112, 795, 768, 3, 6, VCLK85_5,        /* 60 Hz */
+         (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 1, 0x39 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1600x900[] = {
+       { 1760, 1600, 48, 32, 926, 900, 3, 5, VCLK97_75,        /* 60 Hz CVT RB */
+         (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x3a },
+       { 2112, 1600, 88, 168, 934, 900, 3, 5, VCLK118_25,      /* 60 Hz CVT */
+         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x3a },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1920x1080[] = {
+       { 2200, 1920, 88, 44, 1125, 1080, 4, 5, VCLK148_5,      /* 60 Hz */
+         (SyncPP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x38 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+/* 16:10 */
+
+static const struct ast_vbios_enhtable res_1280x800[] = {
+       { 1440, 1280, 48, 32, 823, 800, 3, 6, VCLK71,           /* 60 Hz RB */
+         (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x35 },
+       { 1680, 1280, 72, 128, 831, 800, 3, 6, VCLK83_5,        /* 60 Hz */
+         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x35 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1440x900[] = {
+       { 1600, 1440, 48, 32, 926, 900, 3, 6, VCLK88_75,        /* 60 Hz RB */
+         (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x36 },
+       { 1904, 1440, 80, 152, 934, 900, 3, 6, VCLK106_5,       /* 60 Hz */
+         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x36 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1680x1050[] = {
+       { 1840, 1680, 48, 32, 1080, 1050, 3, 6, VCLK119,        /* 60 Hz RB */
+         (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x37 },
+       { 2240, 1680, 104, 176, 1089, 1050, 3, 6, VCLK146_25,   /* 60 Hz */
+         (SyncPN | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo), 60, 2, 0x37 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+static const struct ast_vbios_enhtable res_1920x1200[] = {
+       { 2080, 1920, 48, 32, 1235, 1200, 3, 6, VCLK154,        /* 60 Hz RB*/
+         (SyncNP | Charx8Dot | LineCompareOff | WideScreenMode | NewModeInfo |
+         AST2500PreCatchCRT), 60, 1, 0x34 },
+       AST_VBIOS_INVALID_MODE,                                 /* end */
+};
+
+/*
+ * VBIOS mode tables
+ */
+
+static const struct ast_vbios_enhtable *res_table_wuxga[] = {
+       &res_1920x1200[0],
+       NULL,
+};
+
+static const struct ast_vbios_enhtable *res_table_fullhd[] = {
+       &res_1920x1080[0],
+       NULL,
+};
+
+static const struct ast_vbios_enhtable *res_table_wsxga_p[] = {
+       &res_1280x800[0],
+       &res_1360x768[0],
+       &res_1440x900[0],
+       &res_1600x900[0],
+       &res_1680x1050[0],
+       NULL,
+};
+
+static const struct ast_vbios_enhtable *res_table[] = {
+       &res_640x480[0],
+       &res_800x600[0],
+       &res_1024x768[0],
+       &res_1152x864[0],
+       &res_1280x1024[0],
+       &res_1600x1200[0],
+       NULL,
+};
+
+static const struct ast_vbios_enhtable *
+__ast_vbios_find_mode_table(const struct ast_vbios_enhtable **vmode_tables,
+                           unsigned int hdisplay,
+                           unsigned int vdisplay)
+{
+       while (*vmode_tables) {
+               if ((*vmode_tables)->hde == hdisplay && (*vmode_tables)->vde == vdisplay)
+                       return *vmode_tables;
+               ++vmode_tables;
+       }
+
+       return NULL;
+}
+
+static const struct ast_vbios_enhtable *ast_vbios_find_mode_table(const struct ast_device *ast,
+                                                                 unsigned int hdisplay,
+                                                                 unsigned int vdisplay)
+{
+       const struct ast_vbios_enhtable *vmode_table = NULL;
+
+       if (ast->support_wuxga)
+               vmode_table = __ast_vbios_find_mode_table(res_table_wuxga, hdisplay, vdisplay);
+       if (!vmode_table && ast->support_fullhd)
+               vmode_table = __ast_vbios_find_mode_table(res_table_fullhd, hdisplay, vdisplay);
+       if (!vmode_table && ast->support_wsxga_p)
+               vmode_table = __ast_vbios_find_mode_table(res_table_wsxga_p, hdisplay, vdisplay);
+       if (!vmode_table)
+               vmode_table = __ast_vbios_find_mode_table(res_table, hdisplay, vdisplay);
+
+       return vmode_table;
+}
+
+const struct ast_vbios_enhtable *ast_vbios_find_mode(const struct ast_device *ast,
+                                                    const struct drm_display_mode *mode)
+{
+       const struct ast_vbios_enhtable *best_vmode = NULL;
+       const struct ast_vbios_enhtable *vmode_table;
+       const struct ast_vbios_enhtable *vmode;
+       u32 refresh_rate;
+
+       vmode_table = ast_vbios_find_mode_table(ast, mode->hdisplay, mode->vdisplay);
+       if (!vmode_table)
+               return NULL;
+
+       refresh_rate = drm_mode_vrefresh(mode);
+
+       for (vmode = vmode_table; ast_vbios_mode_is_valid(vmode); ++vmode) {
+               if (((mode->flags & DRM_MODE_FLAG_NVSYNC) && (vmode->flags & PVSync)) ||
+                   ((mode->flags & DRM_MODE_FLAG_PVSYNC) && (vmode->flags & NVSync)) ||
+                   ((mode->flags & DRM_MODE_FLAG_NHSYNC) && (vmode->flags & PHSync)) ||
+                   ((mode->flags & DRM_MODE_FLAG_PHSYNC) && (vmode->flags & NHSync))) {
+                       continue;
+               }
+               if (vmode->refresh_rate <= refresh_rate &&
+                   (!best_vmode || vmode->refresh_rate > best_vmode->refresh_rate))
+                       best_vmode = vmode;
+       }
+
+       return best_vmode;
+}
diff --git a/drivers/gpu/drm/ast/ast_vbios.h b/drivers/gpu/drm/ast/ast_vbios.h
new file mode 100644 (file)
index 0000000..8cf0250
--- /dev/null
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright (c) 2005 ASPEED Technology Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the authors not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  The authors makes no representations
+ * about the suitability of this software for any purpose.  It is provided
+ * "as is" without express or implied warranty.
+ *
+ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+/* Ported from xf86-video-ast driver */
+
+#ifndef AST_VBIOS_H
+#define AST_VBIOS_H
+
+#include <linux/types.h>
+
+struct ast_device;
+struct drm_display_mode;
+
+#define Charx8Dot               0x00000001
+#define HalfDCLK                0x00000002
+#define DoubleScanMode          0x00000004
+#define LineCompareOff          0x00000008
+#define HBorder                 0x00000020
+#define VBorder                 0x00000010
+#define WideScreenMode         0x00000100
+#define NewModeInfo            0x00000200
+#define NHSync                 0x00000400
+#define PHSync                 0x00000800
+#define NVSync                 0x00001000
+#define PVSync                 0x00002000
+#define SyncPP                 (PVSync | PHSync)
+#define SyncPN                 (PVSync | NHSync)
+#define SyncNP                 (NVSync | PHSync)
+#define SyncNN                 (NVSync | NHSync)
+#define AST2500PreCatchCRT             0x00004000
+
+/* DCLK Index */
+#define VCLK25_175             0x00
+#define VCLK28_322             0x01
+#define VCLK31_5               0x02
+#define VCLK36                 0x03
+#define VCLK40                 0x04
+#define VCLK49_5               0x05
+#define VCLK50                 0x06
+#define VCLK56_25              0x07
+#define VCLK65                 0x08
+#define VCLK75                 0x09
+#define VCLK78_75              0x0a
+#define VCLK94_5               0x0b
+#define VCLK108                        0x0c
+#define VCLK135                        0x0d
+#define VCLK157_5              0x0e
+#define VCLK162                        0x0f
+/* #define VCLK193_25          0x10 */
+#define VCLK154                        0x10
+#define VCLK83_5               0x11
+#define VCLK106_5              0x12
+#define VCLK146_25             0x13
+#define VCLK148_5              0x14
+#define VCLK71                 0x15
+#define VCLK88_75              0x16
+#define VCLK119                        0x17
+#define VCLK85_5               0x18
+#define VCLK97_75              0x19
+#define VCLK118_25             0x1a
+
+struct ast_vbios_enhtable {
+       u32 ht;
+       u32 hde;
+       u32 hfp;
+       u32 hsync;
+       u32 vt;
+       u32 vde;
+       u32 vfp;
+       u32 vsync;
+       u32 dclk_index;
+       u32 flags;
+       u32 refresh_rate;
+       u32 refresh_rate_index;
+       u32 mode_id;
+};
+
+#define AST_VBIOS_INVALID_MODE \
+       {0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u}
+
+static inline bool ast_vbios_mode_is_valid(const struct ast_vbios_enhtable *vmode)
+{
+       return vmode->ht && vmode->vt && vmode->refresh_rate;
+}
+
+const struct ast_vbios_enhtable *ast_vbios_find_mode(const struct ast_device *ast,
+                                                    const struct drm_display_mode *mode);
+
+#endif