LG Gram 2021 laptop 17Z95P-K.ADE9U1 OpRegion has FW size: 0x2200 VBT size: 0x2000 BDB offset: 0x30 BDB size: 0x216e Add intel_init_opregion_quirks to use FW size as VBT size on LG Gram 17Z95P-K.ADE9U1 and update intel_bios_is_valid_vbt to use FW size, instead of VBT size if the quirk is applied, in range_overflows_t for BDB size overflow check. This fixes: https://gitlab.freedesktop.org/drm/intel/-/issues/4763 Signed-off-by: H.J. Lu <hjl.tools@xxxxxxxxx> -- H.J.
From 228e4a56101adf299c8635c7cba900185b9256d0 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@xxxxxxxxx> Date: Tue, 7 Jun 2022 19:00:18 -0700 Subject: [PATCH] drm/i915/bios: Workaround broken video BIOS in LG Gram 2021 LG Gram 2021 laptop 17Z95P-K.ADE9U1 OpRegion has FW size: 0x2200 VBT size: 0x2000 BDB offset: 0x30 BDB size: 0x216e Add intel_init_opregion_quirks to use FW size as VBT size on LG Gram 17Z95P-K.ADE9U1 and update intel_bios_is_valid_vbt to use FW size, instead of VBT size if the quirk is applied, in range_overflows_t for BDB size overflow check. This fixes: https://gitlab.freedesktop.org/drm/intel/-/issues/4763 Signed-off-by: H.J. Lu <hjl.tools@xxxxxxxxx> --- drivers/gpu/drm/i915/display/intel_bios.c | 8 ++-- drivers/gpu/drm/i915/display/intel_opregion.c | 3 ++ drivers/gpu/drm/i915/display/intel_quirks.c | 40 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_quirks.h | 2 + 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index e0e4e9b62d8d..bf4fb3ca617e 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -39,6 +39,7 @@ #include "intel_display.h" #include "intel_display_types.h" #include "intel_gmbus.h" +#include "intel_quirks.h" #define _INTEL_BIOS_PRIVATE #include "intel_vbt_defs.h" @@ -2999,16 +3000,17 @@ bool intel_bios_is_valid_vbt(struct intel_display *display, return false; } - size = vbt->vbt_size; - if (range_overflows_t(size_t, vbt->bdb_offset, sizeof(struct bdb_header), - size)) { + vbt->vbt_size)) { drm_dbg_kms(display->drm, "BDB header incomplete\n"); return false; } + if (!intel_has_quirk(display, QUIRK_USE_FW_SIZE_AS_VBT_SIZE)) + size = vbt->vbt_size; + bdb = get_bdb_header(vbt); if (range_overflows_t(size_t, vbt->bdb_offset, bdb->bdb_size, size)) { drm_dbg_kms(display->drm, "BDB incomplete\n"); diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c index 0eaa6cd6fe80..b17c91a56ea5 100644 --- a/drivers/gpu/drm/i915/display/intel_opregion.c +++ b/drivers/gpu/drm/i915/display/intel_opregion.c @@ -38,6 +38,7 @@ #include "intel_display_types.h" #include "intel_opregion.h" #include "intel_pci_config.h" +#include "intel_quirks.h" #define OPREGION_HEADER_OFFSET 0 #define OPREGION_ACPI_OFFSET 0x100 @@ -969,6 +970,8 @@ int intel_opregion_setup(struct intel_display *display) if (dmi_check_system(intel_no_opregion_vbt)) goto out; + intel_init_opregion_quirks(display); + if (opregion->header->over.major >= 2 && opregion->asle && opregion->asle->rvda && opregion->asle->rvds) { resource_size_t rvda = opregion->asle->rvda; diff --git a/drivers/gpu/drm/i915/display/intel_quirks.c b/drivers/gpu/drm/i915/display/intel_quirks.c index 8b30e9fd936e..5a9d1d83cc78 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.c +++ b/drivers/gpu/drm/i915/display/intel_quirks.c @@ -166,6 +166,36 @@ static const struct intel_dmi_quirk intel_dmi_quirks[] = { }, }; +static void quirk_opregion_use_fw_size_as_vbt_size(struct intel_display *display) +{ + intel_set_quirk(display, QUIRK_USE_FW_SIZE_AS_VBT_SIZE); + drm_info(display->drm, "Applying FW size as VBT size quirk in OpRegion\n"); +} + +static int intel_dmi_opregion_use_fw_size_as_vbt_size(const struct dmi_system_id *id) +{ + DRM_INFO("Use FW size as VBT size on %s in OpRegion\n", id->ident); + return 1; +} + +static const struct intel_dmi_quirk intel_dmi_opregion_quirks[] = { + { + .dmi_id_list = &(const struct dmi_system_id[]) { + { + .callback = intel_dmi_opregion_use_fw_size_as_vbt_size, + .ident = "LG Gram 17Z95P-K.ADE9U1", + .matches = {DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "17Z95P-K.ADE9U1"), + DMI_EXACT_MATCH(DMI_BIOS_VERSION, "T4ZF0040 X64"), + DMI_EXACT_MATCH(DMI_BIOS_DATE, "10/06/2021"), + }, + }, + { } + }, + .hook = quirk_opregion_use_fw_size_as_vbt_size, + }, +}; + static struct intel_quirk intel_quirks[] = { /* Lenovo U160 cannot use SSC on LVDS */ { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable }, @@ -296,3 +326,13 @@ bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk) { return intel_dp->quirks.mask & BIT(quirk); } + +void intel_init_opregion_quirks(struct intel_display *display) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(intel_dmi_opregion_quirks); i++) { + if (dmi_check_system(*intel_dmi_opregion_quirks[i].dmi_id_list) != 0) + intel_dmi_opregion_quirks[i].hook(display); + } +} diff --git a/drivers/gpu/drm/i915/display/intel_quirks.h b/drivers/gpu/drm/i915/display/intel_quirks.h index cafdebda7535..00a0abd09224 100644 --- a/drivers/gpu/drm/i915/display/intel_quirks.h +++ b/drivers/gpu/drm/i915/display/intel_quirks.h @@ -20,6 +20,7 @@ enum intel_quirk_id { QUIRK_LVDS_SSC_DISABLE, QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK, QUIRK_FW_SYNC_LEN, + QUIRK_USE_FW_SIZE_AS_VBT_SIZE, }; void intel_init_quirks(struct intel_display *display); @@ -27,5 +28,6 @@ void intel_init_dpcd_quirks(struct intel_dp *intel_dp, const struct drm_dp_dpcd_ident *ident); bool intel_has_quirk(struct intel_display *display, enum intel_quirk_id quirk); bool intel_has_dpcd_quirk(struct intel_dp *intel_dp, enum intel_quirk_id quirk); +void intel_init_opregion_quirks(struct intel_display *display); #endif /* __INTEL_QUIRKS_H__ */ -- 2.48.1