Message ID | 20250129095840.20629-11-tzimmermann@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/ast: Clean up display-mode detection and validation | expand |
On 29/01/2025 10:54, Thomas Zimmermann wrote: > 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) Thanks for this v2, I find it much more readable than the previous big switch. > > Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> > Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com> > --- > drivers/gpu/drm/ast/Makefile | 1 + > drivers/gpu/drm/ast/ast_dp.c | 1 + > drivers/gpu/drm/ast/ast_drv.h | 18 +-- > drivers/gpu/drm/ast/ast_mode.c | 77 +--------- > drivers/gpu/drm/ast/ast_tables.h | 177 ----------------------- > drivers/gpu/drm/ast/ast_vbios.c | 241 +++++++++++++++++++++++++++++++ > drivers/gpu/drm/ast/ast_vbios.h | 108 ++++++++++++++ > 7 files changed, 360 insertions(+), 263 deletions(-) > create mode 100644 drivers/gpu/drm/ast/ast_vbios.c > create mode 100644 drivers/gpu/drm/ast/ast_vbios.h > > diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile > index 47da848fa3fc1..3107ea9c7bf55 100644 > --- a/drivers/gpu/drm/ast/Makefile > +++ b/drivers/gpu/drm/ast/Makefile > @@ -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 > diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c > index 2d7482a65f62a..37551c67e6c87 100644 > --- a/drivers/gpu/drm/ast/ast_dp.c > +++ b/drivers/gpu/drm/ast/ast_dp.c > @@ -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) > { > diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h > index 4e3a88f8a85ca..9309cc5e81b0f 100644 > --- a/drivers/gpu/drm/ast/ast_drv.h > +++ b/drivers/gpu/drm/ast/ast_drv.h > @@ -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; > diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c > index 3f437f871a357..14c0c281a6834 100644 > --- a/drivers/gpu/drm/ast/ast_mode.c > +++ b/drivers/gpu/drm/ast/ast_mode.c > @@ -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) > diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h > index 4367817b2f806..f1c9f7e1f1fcd 100644 > --- a/drivers/gpu/drm/ast/ast_tables.h > +++ b/drivers/gpu/drm/ast/ast_tables.h > @@ -33,54 +33,6 @@ > #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 > index 0000000000000..0953e6dd39761 > --- /dev/null > +++ b/drivers/gpu/drm/ast/ast_vbios.c > @@ -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 > index 0000000000000..8cf025010594c > --- /dev/null > +++ b/drivers/gpu/drm/ast/ast_vbios.h > @@ -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
diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index 47da848fa3fc1..3107ea9c7bf55 100644 --- a/drivers/gpu/drm/ast/Makefile +++ b/drivers/gpu/drm/ast/Makefile @@ -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 diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index 2d7482a65f62a..37551c67e6c87 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -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) { diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 4e3a88f8a85ca..9309cc5e81b0f 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -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; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 3f437f871a357..14c0c281a6834 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -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) diff --git a/drivers/gpu/drm/ast/ast_tables.h b/drivers/gpu/drm/ast/ast_tables.h index 4367817b2f806..f1c9f7e1f1fcd 100644 --- a/drivers/gpu/drm/ast/ast_tables.h +++ b/drivers/gpu/drm/ast/ast_tables.h @@ -33,54 +33,6 @@ #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 index 0000000000000..0953e6dd39761 --- /dev/null +++ b/drivers/gpu/drm/ast/ast_vbios.c @@ -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 index 0000000000000..8cf025010594c --- /dev/null +++ b/drivers/gpu/drm/ast/ast_vbios.h @@ -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