From 228e4a56101adf299c8635c7cba900185b9256d0 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
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@gmail.com>
---
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(-)
@@ -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");
@@ -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;
@@ -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);
+ }
+}
@@ -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
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@gmail.com>