Commit c7c7eb5e authored by Tvrtko Ursulin's avatar Tvrtko Ursulin Committed by Ard Biesheuvel
Browse files

efi: sysfb_efi: Fix efidrmfb and simpledrmfb on Valve Steam Deck



Valve Steam Deck has a 800x1280 portrait screen installed in a landscape
orientation. The firmware offers a software-rotated 1280x800 mode, which
GRUB can be made to switch to when displaying a boot menu. If this mode
was selected frame buffer drivers will see this fake mode and fbcon
rendering will be corrupted.

Let us therefore add a selective quirk inside the current "swap with and
height" handling, which will detect this exact mode and fix it up back to
the native one.

This will allow the DRM-based framebuffer drivers to detect the correct
mode, apply the existing panel orientation quirk, and render the console
in landscape mode with no corruption.

Signed-off-by: default avatarTvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Melissa Wen <mwen@igalia.com>
Cc: linux-efi@vger.kernel.org
Tested-by: Melissa Wen <mwen@igalia.com> # v3
Reviewed-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
[ardb: use local var to refer to screen_info]
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 7f2f1fd6
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -242,6 +242,33 @@ static int __init efifb_swap_width_height(const struct dmi_system_id *id)
	return 1;
}

struct efifb_mode_fixup {
	unsigned int width;
	unsigned int height;
	unsigned int linelength;
};

static int __init
efifb_check_and_swap_width_height(const struct dmi_system_id *id)
{
	const struct efifb_mode_fixup *data = id->driver_data;
	struct screen_info *si = &screen_info;

	if (data->width == si->lfb_width && data->height == si->lfb_height) {
		swap(si->lfb_width, si->lfb_height);
		si->lfb_linelength = data->linelength;
		si->lfb_size = data->linelength * data->width;
	}

	return 1;
}

static const struct efifb_mode_fixup efifb_steamdeck_mode_fixup __initconst = {
	.width = 1280,
	.height = 800,
	.linelength = 3328,
};

/*
 * Some devices have a portrait LCD but advertise a landscape resolution (and
 * pitch). We simply swap width and height for these devices so that we can
@@ -297,6 +324,26 @@ static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
		},
		.callback = efifb_swap_width_height,
	},
	{
		/* Valve Steam Deck (Jupiter) */
		.matches = {
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Jupiter"),
			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
		},
		.callback = efifb_check_and_swap_width_height,
		.driver_data = (void *)&efifb_steamdeck_mode_fixup,
	},
	{
		/* Valve Steam Deck (Galileo) */
		.matches = {
			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Valve"),
			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Galileo"),
			DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "1"),
		},
		.callback = efifb_check_and_swap_width_height,
		.driver_data = (void *)&efifb_steamdeck_mode_fixup,
	},
	{},
};