From: Tvrtko Ursulin <[email protected]>

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: Tvrtko Ursulin <[email protected]>
Cc: Thomas Zimmermann <[email protected]>
Cc: Ard Biesheuvel <[email protected]>
Cc: Melissa Wen <[email protected]>
Cc: [email protected]
Tested-by: Melissa Wen <[email protected]> # v3
Reviewed-by: Thomas Zimmermann <[email protected]>
---
 drivers/firmware/efi/sysfb_efi.c | 47 ++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/firmware/efi/sysfb_efi.c b/drivers/firmware/efi/sysfb_efi.c
index 85f6399d5e1f..88e4fd4b0a3f 100644
--- a/drivers/firmware/efi/sysfb_efi.c
+++ b/drivers/firmware/efi/sysfb_efi.c
@@ -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;
+
+       if (data->width == screen_info.lfb_width &&
+           data->height == screen_info.lfb_height) {
+               swap(screen_info.lfb_width, screen_info.lfb_height);
+               screen_info.lfb_linelength = data->linelength;
+               screen_info.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,
+       },
        {},
 };
 
-- 
2.52.0

Reply via email to