| From d02f1aa39189e0619c3525d5cd03254e61bf606a Mon Sep 17 00:00:00 2001 |
| From: Hans de Goede <hdegoede@redhat.com> |
| Date: Sun, 21 Jul 2019 17:24:18 +0200 |
| Subject: x86/sysfb_efi: Add quirks for some devices with swapped width and height |
| |
| From: Hans de Goede <hdegoede@redhat.com> |
| |
| commit d02f1aa39189e0619c3525d5cd03254e61bf606a upstream. |
| |
| Some Lenovo 2-in-1s with a detachable keyboard have a portrait screen but |
| advertise a landscape resolution and pitch, resulting in a messed up |
| display if the kernel tries to show anything on the efifb (because of the |
| wrong pitch). |
| |
| Fix this by adding a new DMI match table for devices which need to have |
| their width and height swapped. |
| |
| At first it was tried to use the existing table for overriding some of the |
| efifb parameters, but some of the affected devices have variants with |
| different LCD resolutions which will not work with hardcoded override |
| values. |
| |
| Reference: https://bugzilla.redhat.com/show_bug.cgi?id=1730783 |
| Signed-off-by: Hans de Goede <hdegoede@redhat.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Cc: stable@vger.kernel.org |
| Link: https://lkml.kernel.org/r/20190721152418.11644-1-hdegoede@redhat.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/kernel/sysfb_efi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 46 insertions(+) |
| |
| --- a/arch/x86/kernel/sysfb_efi.c |
| +++ b/arch/x86/kernel/sysfb_efi.c |
| @@ -231,9 +231,55 @@ static const struct dmi_system_id efifb_ |
| {}, |
| }; |
| |
| +/* |
| + * 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 |
| + * correctly deal with some of them coming with multiple resolutions. |
| + */ |
| +static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = { |
| + { |
| + /* |
| + * Lenovo MIIX310-10ICR, only some batches have the troublesome |
| + * 800x1280 portrait screen. Luckily the portrait version has |
| + * its own BIOS version, so we match on that. |
| + */ |
| + .matches = { |
| + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"), |
| + DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1HCN44WW"), |
| + }, |
| + }, |
| + { |
| + /* Lenovo MIIX 320-10ICR with 800x1280 portrait screen */ |
| + .matches = { |
| + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, |
| + "Lenovo MIIX 320-10ICR"), |
| + }, |
| + }, |
| + { |
| + /* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */ |
| + .matches = { |
| + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, |
| + "Lenovo ideapad D330-10IGM"), |
| + }, |
| + }, |
| + {}, |
| +}; |
| + |
| __init void sysfb_apply_efi_quirks(void) |
| { |
| if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI || |
| !(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS)) |
| dmi_check_system(efifb_dmi_system_table); |
| + |
| + if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI && |
| + dmi_check_system(efifb_dmi_swap_width_height)) { |
| + u16 temp = screen_info.lfb_width; |
| + |
| + screen_info.lfb_width = screen_info.lfb_height; |
| + screen_info.lfb_height = temp; |
| + screen_info.lfb_linelength = 4 * screen_info.lfb_width; |
| + } |
| } |