mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 17:25:38 +00:00
efi/gop: Allow automatically choosing the best mode
Add the ability to automatically pick the highest resolution video mode (defined as the product of vertical and horizontal resolution) by using a command-line argument of the form video=efifb:auto If there are multiple modes with the highest resolution, pick one with the highest color depth. Signed-off-by: Arvind Sankar <nivedita@alum.mit.edu> Link: https://lore.kernel.org/r/20200328160601.378299-2-nivedita@alum.mit.edu Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
9a1663bc4d
commit
45d97a749e
@ -57,4 +57,10 @@ mode=n
|
||||
"rgb" or "bgr" to match specifically those pixel formats, or a number
|
||||
for a mode with matching bits per pixel.
|
||||
|
||||
auto
|
||||
The EFI stub will choose the mode with the highest resolution (product
|
||||
of horizontal and vertical resolution). If there are multiple modes
|
||||
with the highest resolution, it will choose one with the highest color
|
||||
depth.
|
||||
|
||||
Edgar Hucek <gimli@dark-green.com>
|
||||
|
@ -18,7 +18,8 @@
|
||||
enum efi_cmdline_option {
|
||||
EFI_CMDLINE_NONE,
|
||||
EFI_CMDLINE_MODE_NUM,
|
||||
EFI_CMDLINE_RES
|
||||
EFI_CMDLINE_RES,
|
||||
EFI_CMDLINE_AUTO
|
||||
};
|
||||
|
||||
static struct {
|
||||
@ -86,6 +87,19 @@ static bool parse_res(char *option, char **next)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_auto(char *option, char **next)
|
||||
{
|
||||
if (!strstarts(option, "auto"))
|
||||
return false;
|
||||
option += strlen("auto");
|
||||
if (*option && *option++ != ',')
|
||||
return false;
|
||||
cmdline.option = EFI_CMDLINE_AUTO;
|
||||
|
||||
*next = option;
|
||||
return true;
|
||||
}
|
||||
|
||||
void efi_parse_option_graphics(char *option)
|
||||
{
|
||||
while (*option) {
|
||||
@ -93,6 +107,8 @@ void efi_parse_option_graphics(char *option)
|
||||
continue;
|
||||
if (parse_res(option, &option))
|
||||
continue;
|
||||
if (parse_auto(option, &option))
|
||||
continue;
|
||||
|
||||
while (*option && *option++ != ',')
|
||||
;
|
||||
@ -211,6 +227,69 @@ static u32 choose_mode_res(efi_graphics_output_protocol_t *gop)
|
||||
return cur_mode;
|
||||
}
|
||||
|
||||
static u32 choose_mode_auto(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_status_t status;
|
||||
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
efi_graphics_output_mode_info_t *info;
|
||||
unsigned long info_size;
|
||||
|
||||
u32 max_mode, cur_mode, best_mode, area;
|
||||
u8 depth;
|
||||
int pf;
|
||||
efi_pixel_bitmask_t pi;
|
||||
u32 m, w, h, a;
|
||||
u8 d;
|
||||
|
||||
mode = efi_table_attr(gop, mode);
|
||||
|
||||
cur_mode = efi_table_attr(mode, mode);
|
||||
max_mode = efi_table_attr(mode, max_mode);
|
||||
|
||||
info = efi_table_attr(mode, info);
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
best_mode = cur_mode;
|
||||
area = w * h;
|
||||
depth = pixel_bpp(pf, pi);
|
||||
|
||||
for (m = 0; m < max_mode; m++) {
|
||||
if (m == cur_mode)
|
||||
continue;
|
||||
|
||||
status = efi_call_proto(gop, query_mode, m,
|
||||
&info_size, &info);
|
||||
if (status != EFI_SUCCESS)
|
||||
continue;
|
||||
|
||||
pf = info->pixel_format;
|
||||
pi = info->pixel_information;
|
||||
w = info->horizontal_resolution;
|
||||
h = info->vertical_resolution;
|
||||
|
||||
efi_bs_call(free_pool, info);
|
||||
|
||||
if (pf == PIXEL_BLT_ONLY || pf >= PIXEL_FORMAT_MAX)
|
||||
continue;
|
||||
a = w * h;
|
||||
if (a < area)
|
||||
continue;
|
||||
d = pixel_bpp(pf, pi);
|
||||
if (a > area || d > depth) {
|
||||
best_mode = m;
|
||||
area = a;
|
||||
depth = d;
|
||||
}
|
||||
}
|
||||
|
||||
return best_mode;
|
||||
}
|
||||
|
||||
static void set_mode(efi_graphics_output_protocol_t *gop)
|
||||
{
|
||||
efi_graphics_output_protocol_mode_t *mode;
|
||||
@ -223,6 +302,9 @@ static void set_mode(efi_graphics_output_protocol_t *gop)
|
||||
case EFI_CMDLINE_RES:
|
||||
new_mode = choose_mode_res(gop);
|
||||
break;
|
||||
case EFI_CMDLINE_AUTO:
|
||||
new_mode = choose_mode_auto(gop);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user