All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
@ 2022-04-05 17:33 Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version Ville Syrjala
                   ` (32 more replies)
  0 siblings, 33 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Several changes to our BDB block handling:

1)
The current way of trusting the version checks to avoid out of
bounds accesses to the BDB blocks is fragile. We might just get
the version check wrong, or the VBT may be corrupted/malicious.
So instead of doing blind accesses into the original data let's
make a copy of each block with a gauranteed minimum size.

2)
The LFP data table pointer stuff is a horrible mess currently.
Let's make that sensible by verifying the pointers ahead of
time, which allows us to trust them 100% when we acually
parse the actual data block.

3)
There's more stuff at the tail end of the LFP data block we
need to parse. The variable size of the fp_timing table makes
that a bit awkward, but with the pointer validation in place
it's not too horrible.

4)
Modern VBTs (seen it on TGL/ADL-P/CML so far) no longer include
the LFP data table pointers block (41) in the VBT. In order to
keep the rest of the code working as is we must therefore
generate the pointers block from scratch.

New stuff in v2:
- Make all the BDB block copies up front
- Split the VBT parsing into two parts and add the EDID
  PNPID->panel_type matching because many modern machines need it

Ville Syrjälä (22):
  drm/i915/bios: Use the cached BDB version
  drm/i915/bios: Make copies of VBT data blocks
  drm/i915/bios: Use the copy of the LFP data table always
  drm/i915/bios: Validate LFP data table pointers
  drm/i915/bios: Trust the LFP data pointers
  drm/i915/bios: Validate the panel_name table
  drm/i915/bios: Reorder panel DTD parsing
  drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  drm/i915/bios: Get access to the tail end of the LFP data block
  drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
  drm/i915/bios: Split parse_driver_features() into two parts
  drm/i915/bios: Split VBT parsing to global vs. panel specific parts
  drm/i915/pps: Split PPS init+sanitize in two
  drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
  drm/i915/bios: Do panel specific VBT parsing later
  drm/i915/bios: Extract get_panel_type()
  drm/i915/bios: Refactor panel_type code
  drm/i915/bios: Determine panel type via PNPID match
  drm/i915/bios: Parse the seamless DRRS min refresh rate
  drm/i915: Respect VBT seamless DRRS min refresh rate
  drm/edid: Extract drm_edid_decode_mfg_id()
  drm/i915/bios: Dump PNPID and panel name

 drivers/gpu/drm/i915/display/icl_dsi.c        |   2 +
 drivers/gpu/drm/i915/display/intel_bios.c     | 883 ++++++++++++++----
 drivers/gpu/drm/i915/display/intel_bios.h     |   3 +
 drivers/gpu/drm/i915/display/intel_dp.c       |   4 +
 drivers/gpu/drm/i915/display/intel_lvds.c     |   2 +
 drivers/gpu/drm/i915/display/intel_panel.c    |  10 +-
 drivers/gpu/drm/i915/display/intel_pps.c      |  35 +-
 drivers/gpu/drm/i915/display/intel_pps.h      |   1 +
 drivers/gpu/drm/i915/display/intel_sdvo.c     |   3 +
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |  22 +
 drivers/gpu/drm/i915/display/vlv_dsi.c        |   2 +
 drivers/gpu/drm/i915/i915_drv.h               |   2 +
 include/drm/drm_edid.h                        |  21 +-
 13 files changed, 810 insertions(+), 180 deletions(-)

-- 
2.35.1


^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 10:10   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 02/22] drm/i915/bios: Make copies of VBT data blocks Ville Syrjala
                   ` (31 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We have the BDB version cached, use it. We're going to have to
start doing some of the BDB block parsing later, at which point
we may no longer have the VBT around anymore (we free it at the
end of intel_bios_init() when it didn't come via OpRegion).

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 54 +++++++++++------------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 556169ce0544..5518f4cfa1b1 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -415,7 +415,7 @@ parse_panel_dtd(struct drm_i915_private *i915,
 	 * try the new generic DTD block first on VBT >= 229, but still fall
 	 * back to trying the old LFP block if that fails.
 	 */
-	if (bdb->version >= 229)
+	if (i915->vbt.version >= 229)
 		parse_generic_dtd(i915, bdb);
 	if (!i915->vbt.lfp_lvds_vbt_mode)
 		parse_lfp_panel_dtd(i915, bdb);
@@ -452,12 +452,12 @@ parse_lfp_backlight(struct drm_i915_private *i915,
 	}
 
 	i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
-	if (bdb->version >= 191) {
+	if (i915->vbt.version >= 191) {
 		size_t exp_size;
 
-		if (bdb->version >= 236)
+		if (i915->vbt.version >= 236)
 			exp_size = sizeof(struct bdb_lfp_backlight_data);
-		else if (bdb->version >= 234)
+		else if (i915->vbt.version >= 234)
 			exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234;
 		else
 			exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191;
@@ -474,14 +474,14 @@ parse_lfp_backlight(struct drm_i915_private *i915,
 	i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
 	i915->vbt.backlight.active_low_pwm = entry->active_low_pwm;
 
-	if (bdb->version >= 234) {
+	if (i915->vbt.version >= 234) {
 		u16 min_level;
 		bool scale;
 
 		level = backlight_data->brightness_level[panel_type].level;
 		min_level = backlight_data->brightness_min_level[panel_type].level;
 
-		if (bdb->version >= 236)
+		if (i915->vbt.version >= 236)
 			scale = backlight_data->brightness_precision_bits[panel_type] == 16;
 		else
 			scale = level > 255;
@@ -581,7 +581,7 @@ parse_general_features(struct drm_i915_private *i915,
 
 	i915->vbt.int_tv_support = general->int_tv_support;
 	/* int_crt_support can't be trusted on earlier platforms */
-	if (bdb->version >= 155 &&
+	if (i915->vbt.version >= 155 &&
 	    (HAS_DDI(i915) || IS_VALLEYVIEW(i915)))
 		i915->vbt.int_crt_support = general->int_crt_support;
 	i915->vbt.lvds_use_ssc = general->enable_ssc;
@@ -589,7 +589,7 @@ parse_general_features(struct drm_i915_private *i915,
 		intel_bios_ssc_frequency(i915, general->ssc_freq);
 	i915->vbt.display_clock_mode = general->display_clock_mode;
 	i915->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
-	if (bdb->version >= 181) {
+	if (i915->vbt.version >= 181) {
 		i915->vbt.orientation = general->rotate_180 ?
 			DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
 			DRM_MODE_PANEL_ORIENTATION_NORMAL;
@@ -597,7 +597,7 @@ parse_general_features(struct drm_i915_private *i915,
 		i915->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
 	}
 
-	if (bdb->version >= 249 && general->afc_startup_config) {
+	if (i915->vbt.version >= 249 && general->afc_startup_config) {
 		i915->vbt.override_afc_startup = true;
 		i915->vbt.override_afc_startup_val = general->afc_startup_config == 0x1 ? 0x0 : 0x7;
 	}
@@ -724,13 +724,13 @@ parse_driver_features(struct drm_i915_private *i915,
 		 * in the wild with the bits correctly populated. Version
 		 * 108 (on i85x) does not have the bits correctly populated.
 		 */
-		if (bdb->version >= 134 &&
+		if (i915->vbt.version >= 134 &&
 		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS &&
 		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
 			i915->vbt.int_lvds_support = 0;
 	}
 
-	if (bdb->version < 228) {
+	if (i915->vbt.version < 228) {
 		drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
 			    driver->drrs_enabled);
 		/*
@@ -753,7 +753,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
 	const struct bdb_lfp_power *power;
 	u8 panel_type = i915->vbt.panel_type;
 
-	if (bdb->version < 228)
+	if (i915->vbt.version < 228)
 		return;
 
 	power = find_section(bdb, BDB_LFP_POWER);
@@ -771,7 +771,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
 	if (!(power->drrs & BIT(panel_type)))
 		i915->vbt.drrs_type = DRRS_TYPE_NONE;
 
-	if (bdb->version >= 232)
+	if (i915->vbt.version >= 232)
 		i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
 }
 
@@ -876,7 +876,7 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
 		break;
 	}
 
-	if (bdb->version >= 173) {
+	if (i915->vbt.version >= 173) {
 		u8 vswing;
 
 		/* Don't read from VBT if module parameter has valid value*/
@@ -919,7 +919,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
 	 * New psr options 0=500us, 1=100us, 2=2500us, 3=0us
 	 * Old decimal value is wake up time in multiples of 100 us.
 	 */
-	if (bdb->version >= 205 &&
+	if (i915->vbt.version >= 205 &&
 	    (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) {
 		switch (psr_table->tp1_wakeup_time) {
 		case 0:
@@ -965,7 +965,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
 		i915->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
 	}
 
-	if (bdb->version >= 226) {
+	if (i915->vbt.version >= 226) {
 		u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
 
 		wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
@@ -1085,7 +1085,7 @@ parse_mipi_config(struct drm_i915_private *i915,
 		return;
 	}
 
-	parse_dsi_backlight_ports(i915, bdb->version, port);
+	parse_dsi_backlight_ports(i915, i915->vbt.version, port);
 
 	/* FIXME is the 90 vs. 270 correct? */
 	switch (config->rotation) {
@@ -1448,7 +1448,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
 	u16 block_size;
 	int index;
 
-	if (bdb->version < 198)
+	if (i915->vbt.version < 198)
 		return;
 
 	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
@@ -2117,31 +2117,31 @@ parse_general_definitions(struct drm_i915_private *i915,
 	if (intel_gmbus_is_valid_pin(i915, bus_pin))
 		i915->vbt.crt_ddc_pin = bus_pin;
 
-	if (bdb->version < 106) {
+	if (i915->vbt.version < 106) {
 		expected_size = 22;
-	} else if (bdb->version < 111) {
+	} else if (i915->vbt.version < 111) {
 		expected_size = 27;
-	} else if (bdb->version < 195) {
+	} else if (i915->vbt.version < 195) {
 		expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE;
-	} else if (bdb->version == 195) {
+	} else if (i915->vbt.version == 195) {
 		expected_size = 37;
-	} else if (bdb->version <= 215) {
+	} else if (i915->vbt.version <= 215) {
 		expected_size = 38;
-	} else if (bdb->version <= 237) {
+	} else if (i915->vbt.version <= 237) {
 		expected_size = 39;
 	} else {
 		expected_size = sizeof(*child);
 		BUILD_BUG_ON(sizeof(*child) < 39);
 		drm_dbg(&i915->drm,
 			"Expected child device config size for VBT version %u not known; assuming %u\n",
-			bdb->version, expected_size);
+			i915->vbt.version, expected_size);
 	}
 
 	/* Flag an error for unexpected size, but continue anyway. */
 	if (defs->child_dev_size != expected_size)
 		drm_err(&i915->drm,
 			"Unexpected child device config size %u (expected %u for VBT version %u)\n",
-			defs->child_dev_size, expected_size, bdb->version);
+			defs->child_dev_size, expected_size, i915->vbt.version);
 
 	/* The legacy sized child device config is the minimum we need. */
 	if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) {
@@ -2497,7 +2497,7 @@ void intel_bios_init(struct drm_i915_private *i915)
 
 	drm_dbg_kms(&i915->drm,
 		    "VBT signature \"%.*s\", BDB version %d\n",
-		    (int)sizeof(vbt->signature), vbt->signature, bdb->version);
+		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
 
 	/* Grab useful general definitions */
 	parse_general_features(i915, bdb);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 02/22] drm/i915/bios: Make copies of VBT data blocks
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-06 13:38   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 03/22] drm/i915/bios: Use the copy of the LFP data table always Ville Syrjala
                   ` (30 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make a copy of each VB data block with a guaranteed minimum
size. The extra (if any) will just be left zeroed.

This means we don't have to worry about going out of bounds
when accessing any of the structure members. Otherwise that
could easliy happen if we simply get the version check wrong,
or if the VBT is broken/malicious.

v2: Don't do arithmetic between bdb header and copy
    of the LFP data block (Jani)
v3: Make all the copies up front

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 230 ++++++++++++++++------
 drivers/gpu/drm/i915/i915_drv.h           |   1 +
 2 files changed, 174 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 5518f4cfa1b1..2e9f639d092e 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
 }
 
 static const void *
-find_section(const void *_bdb, enum bdb_block_id section_id)
+find_raw_section(const void *_bdb, enum bdb_block_id section_id)
 {
 	const struct bdb_header *bdb = _bdb;
 	const u8 *base = _bdb;
@@ -118,6 +118,124 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
 	return NULL;
 }
 
+/*
+ * Offset from the start of BDB to the start of the
+ * block data (just past the block header).
+ */
+static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
+{
+	const void *block;
+
+	block = find_raw_section(bdb, section_id);
+	if (!block)
+		return 0;
+
+	return block - bdb;
+}
+
+struct bdb_block_entry {
+	struct list_head node;
+	enum bdb_block_id section_id;
+	u8 data[];
+};
+
+static const void *
+find_section(struct drm_i915_private *i915,
+	     enum bdb_block_id section_id)
+{
+	struct bdb_block_entry *entry;
+
+	list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
+		if (entry->section_id == section_id)
+			return entry->data + 3;
+	}
+
+	return NULL;
+}
+
+static const struct {
+	enum bdb_block_id section_id;
+	size_t min_size;
+} bdb_blocks[] = {
+	{ .section_id = BDB_GENERAL_FEATURES,
+	  .min_size = sizeof(struct bdb_general_features), },
+	{ .section_id = BDB_GENERAL_DEFINITIONS,
+	  .min_size = sizeof(struct bdb_general_definitions), },
+	{ .section_id = BDB_PSR,
+	  .min_size = sizeof(struct bdb_psr), },
+	{ .section_id = BDB_DRIVER_FEATURES,
+	  .min_size = sizeof(struct bdb_driver_features), },
+	{ .section_id = BDB_SDVO_LVDS_OPTIONS,
+	  .min_size = sizeof(struct bdb_sdvo_lvds_options), },
+	{ .section_id = BDB_SDVO_PANEL_DTDS,
+	  .min_size = sizeof(struct bdb_sdvo_panel_dtds), },
+	{ .section_id = BDB_EDP,
+	  .min_size = sizeof(struct bdb_edp), },
+	{ .section_id = BDB_LVDS_OPTIONS,
+	  .min_size = sizeof(struct bdb_lvds_options), },
+	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
+	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
+	{ .section_id = BDB_LVDS_LFP_DATA,
+	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
+	{ .section_id = BDB_LVDS_BACKLIGHT,
+	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
+	{ .section_id = BDB_LFP_POWER,
+	  .min_size = sizeof(struct bdb_lfp_power), },
+	{ .section_id = BDB_MIPI_CONFIG,
+	  .min_size = sizeof(struct bdb_mipi_config), },
+	{ .section_id = BDB_MIPI_SEQUENCE,
+	  .min_size = sizeof(struct bdb_mipi_sequence) },
+	{ .section_id = BDB_COMPRESSION_PARAMETERS,
+	  .min_size = sizeof(struct bdb_compression_parameters), },
+	{ .section_id = BDB_GENERIC_DTD,
+	  .min_size = sizeof(struct bdb_generic_dtd), },
+};
+
+static void
+init_bdb_block(struct drm_i915_private *i915,
+	       const void *bdb, enum bdb_block_id section_id,
+	       size_t min_size)
+{
+	struct bdb_block_entry *entry;
+	const void *block;
+	size_t block_size;
+
+	block = find_raw_section(bdb, section_id);
+	if (!block)
+		return;
+
+	block_size = get_blocksize(block);
+
+	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
+			GFP_KERNEL);
+	if (!entry)
+		return;
+
+	entry->section_id = section_id;
+	memcpy(entry->data, block - 3, block_size + 3);
+
+	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
+		    section_id, block_size, min_size);
+
+	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
+}
+
+static void init_bdb_blocks(struct drm_i915_private *i915,
+			    const void *bdb)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
+		enum bdb_block_id section_id = bdb_blocks[i].section_id;
+		size_t min_size = bdb_blocks[i].min_size;
+
+		drm_WARN(&i915->drm, min_size == 0,
+			 "Block %d min_size is zero\n", section_id);
+
+		init_bdb_block(i915, bdb, section_id, min_size);
+	}
+}
+
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
 			const struct lvds_dvo_timing *dvo_timing)
@@ -199,7 +317,7 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
 		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
 		   int index)
 {
-	size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
+	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
 	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
 	size_t ofs;
 
@@ -214,15 +332,14 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
 
 /* Parse general panel options */
 static void
-parse_panel_options(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_panel_options(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_options *lvds_options;
 	int panel_type;
 	int drrs_mode;
 	int ret;
 
-	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
 		return;
 
@@ -285,11 +402,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
 	struct drm_display_mode *panel_fixed_mode;
 	int panel_type = i915->vbt.panel_type;
 
-	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
 	if (!lvds_lfp_data)
 		return;
 
-	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
 	if (!lvds_lfp_data_ptrs)
 		return;
 
@@ -325,15 +442,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
 }
 
 static void
-parse_generic_dtd(struct drm_i915_private *i915,
-		  const struct bdb_header *bdb)
+parse_generic_dtd(struct drm_i915_private *i915)
 {
 	const struct bdb_generic_dtd *generic_dtd;
 	const struct generic_dtd_entry *dtd;
 	struct drm_display_mode *panel_fixed_mode;
 	int num_dtd;
 
-	generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
+	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
 	if (!generic_dtd)
 		return;
 
@@ -416,21 +532,20 @@ parse_panel_dtd(struct drm_i915_private *i915,
 	 * back to trying the old LFP block if that fails.
 	 */
 	if (i915->vbt.version >= 229)
-		parse_generic_dtd(i915, bdb);
+		parse_generic_dtd(i915);
 	if (!i915->vbt.lfp_lvds_vbt_mode)
 		parse_lfp_panel_dtd(i915, bdb);
 }
 
 static void
-parse_lfp_backlight(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_lfp_backlight(struct drm_i915_private *i915)
 {
 	const struct bdb_lfp_backlight_data *backlight_data;
 	const struct lfp_backlight_data_entry *entry;
 	int panel_type = i915->vbt.panel_type;
 	u16 level;
 
-	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
+	backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
 	if (!backlight_data)
 		return;
 
@@ -514,8 +629,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
 
 /* Try to find sdvo panel data */
 static void
-parse_sdvo_panel_data(struct drm_i915_private *i915,
-		      const struct bdb_header *bdb)
+parse_sdvo_panel_data(struct drm_i915_private *i915)
 {
 	const struct bdb_sdvo_panel_dtds *dtds;
 	struct drm_display_mode *panel_fixed_mode;
@@ -531,14 +645,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
 	if (index == -1) {
 		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 
-		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+		sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
 		if (!sdvo_lvds_options)
 			return;
 
 		index = sdvo_lvds_options->panel_type;
 	}
 
-	dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+	dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
 	if (!dtds)
 		return;
 
@@ -570,12 +684,11 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
 }
 
 static void
-parse_general_features(struct drm_i915_private *i915,
-		       const struct bdb_header *bdb)
+parse_general_features(struct drm_i915_private *i915)
 {
 	const struct bdb_general_features *general;
 
-	general = find_section(bdb, BDB_GENERAL_FEATURES);
+	general = find_section(i915, BDB_GENERAL_FEATURES);
 	if (!general)
 		return;
 
@@ -695,12 +808,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
 }
 
 static void
-parse_driver_features(struct drm_i915_private *i915,
-		      const struct bdb_header *bdb)
+parse_driver_features(struct drm_i915_private *i915)
 {
 	const struct bdb_driver_features *driver;
 
-	driver = find_section(bdb, BDB_DRIVER_FEATURES);
+	driver = find_section(i915, BDB_DRIVER_FEATURES);
 	if (!driver)
 		return;
 
@@ -747,8 +859,7 @@ parse_driver_features(struct drm_i915_private *i915,
 }
 
 static void
-parse_power_conservation_features(struct drm_i915_private *i915,
-				  const struct bdb_header *bdb)
+parse_power_conservation_features(struct drm_i915_private *i915)
 {
 	const struct bdb_lfp_power *power;
 	u8 panel_type = i915->vbt.panel_type;
@@ -756,7 +867,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
 	if (i915->vbt.version < 228)
 		return;
 
-	power = find_section(bdb, BDB_LFP_POWER);
+	power = find_section(i915, BDB_LFP_POWER);
 	if (!power)
 		return;
 
@@ -776,14 +887,14 @@ parse_power_conservation_features(struct drm_i915_private *i915,
 }
 
 static void
-parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
+parse_edp(struct drm_i915_private *i915)
 {
 	const struct bdb_edp *edp;
 	const struct edp_power_seq *edp_pps;
 	const struct edp_fast_link_params *edp_link_params;
 	int panel_type = i915->vbt.panel_type;
 
-	edp = find_section(bdb, BDB_EDP);
+	edp = find_section(i915, BDB_EDP);
 	if (!edp)
 		return;
 
@@ -894,13 +1005,13 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
 }
 
 static void
-parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
+parse_psr(struct drm_i915_private *i915)
 {
 	const struct bdb_psr *psr;
 	const struct psr_table *psr_table;
 	int panel_type = i915->vbt.panel_type;
 
-	psr = find_section(bdb, BDB_PSR);
+	psr = find_section(i915, BDB_PSR);
 	if (!psr) {
 		drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
 		return;
@@ -1034,8 +1145,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
 }
 
 static void
-parse_mipi_config(struct drm_i915_private *i915,
-		  const struct bdb_header *bdb)
+parse_mipi_config(struct drm_i915_private *i915)
 {
 	const struct bdb_mipi_config *start;
 	const struct mipi_config *config;
@@ -1058,7 +1168,7 @@ parse_mipi_config(struct drm_i915_private *i915,
 	/* Parse #52 for panel index used from panel_type already
 	 * parsed
 	 */
-	start = find_section(bdb, BDB_MIPI_CONFIG);
+	start = find_section(i915, BDB_MIPI_CONFIG);
 	if (!start) {
 		drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
 		return;
@@ -1354,8 +1464,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
 }
 
 static void
-parse_mipi_sequence(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_mipi_sequence(struct drm_i915_private *i915)
 {
 	int panel_type = i915->vbt.panel_type;
 	const struct bdb_mipi_sequence *sequence;
@@ -1368,7 +1477,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
 	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
 		return;
 
-	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
+	sequence = find_section(i915, BDB_MIPI_SEQUENCE);
 	if (!sequence) {
 		drm_dbg_kms(&i915->drm,
 			    "No MIPI Sequence found, parsing complete\n");
@@ -1439,8 +1548,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
 }
 
 static void
-parse_compression_parameters(struct drm_i915_private *i915,
-			     const struct bdb_header *bdb)
+parse_compression_parameters(struct drm_i915_private *i915)
 {
 	const struct bdb_compression_parameters *params;
 	struct intel_bios_encoder_data *devdata;
@@ -1451,7 +1559,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
 	if (i915->vbt.version < 198)
 		return;
 
-	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
+	params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
 	if (params) {
 		/* Sanity checks */
 		if (params->entry_size != sizeof(params->data[0])) {
@@ -2086,8 +2194,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
 }
 
 static void
-parse_general_definitions(struct drm_i915_private *i915,
-			  const struct bdb_header *bdb)
+parse_general_definitions(struct drm_i915_private *i915)
 {
 	const struct bdb_general_definitions *defs;
 	struct intel_bios_encoder_data *devdata;
@@ -2097,7 +2204,7 @@ parse_general_definitions(struct drm_i915_private *i915,
 	u16 block_size;
 	int bus_pin;
 
-	defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
 	if (!defs) {
 		drm_dbg_kms(&i915->drm,
 			    "No general definition block is found, no devices defined.\n");
@@ -2466,6 +2573,7 @@ void intel_bios_init(struct drm_i915_private *i915)
 	const struct bdb_header *bdb;
 
 	INIT_LIST_HEAD(&i915->vbt.display_devices);
+	INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
 
 	if (!HAS_DISPLAY(i915)) {
 		drm_dbg_kms(&i915->drm,
@@ -2499,22 +2607,24 @@ void intel_bios_init(struct drm_i915_private *i915)
 		    "VBT signature \"%.*s\", BDB version %d\n",
 		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
 
+	init_bdb_blocks(i915, bdb);
+
 	/* Grab useful general definitions */
-	parse_general_features(i915, bdb);
-	parse_general_definitions(i915, bdb);
-	parse_panel_options(i915, bdb);
+	parse_general_features(i915);
+	parse_general_definitions(i915);
+	parse_panel_options(i915);
 	parse_panel_dtd(i915, bdb);
-	parse_lfp_backlight(i915, bdb);
-	parse_sdvo_panel_data(i915, bdb);
-	parse_driver_features(i915, bdb);
-	parse_power_conservation_features(i915, bdb);
-	parse_edp(i915, bdb);
-	parse_psr(i915, bdb);
-	parse_mipi_config(i915, bdb);
-	parse_mipi_sequence(i915, bdb);
+	parse_lfp_backlight(i915);
+	parse_sdvo_panel_data(i915);
+	parse_driver_features(i915);
+	parse_power_conservation_features(i915);
+	parse_edp(i915);
+	parse_psr(i915);
+	parse_mipi_config(i915);
+	parse_mipi_sequence(i915);
 
 	/* Depends on child device list */
-	parse_compression_parameters(i915, bdb);
+	parse_compression_parameters(i915);
 
 out:
 	if (!vbt) {
@@ -2536,14 +2646,20 @@ void intel_bios_init(struct drm_i915_private *i915)
  */
 void intel_bios_driver_remove(struct drm_i915_private *i915)
 {
-	struct intel_bios_encoder_data *devdata, *n;
+	struct intel_bios_encoder_data *devdata, *nd;
+	struct bdb_block_entry *entry, *ne;
 
-	list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
+	list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
 		list_del(&devdata->node);
 		kfree(devdata->dsc);
 		kfree(devdata);
 	}
 
+	list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
+		list_del(&entry->node);
+		kfree(entry);
+	}
+
 	kfree(i915->vbt.sdvo_lvds_vbt_mode);
 	i915->vbt.sdvo_lvds_vbt_mode = NULL;
 	kfree(i915->vbt.lfp_lvds_vbt_mode);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 06e7c2802c5e..9274417cd87a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -380,6 +380,7 @@ struct intel_vbt_data {
 	int crt_ddc_pin;
 
 	struct list_head display_devices;
+	struct list_head bdb_blocks;
 
 	struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
 	struct sdvo_device_mapping sdvo_mappings[2];
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 03/22] drm/i915/bios: Use the copy of the LFP data table always
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 02/22] drm/i915/bios: Make copies of VBT data blocks Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 10:36   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 04/22] drm/i915/bios: Validate LFP data table pointers Ville Syrjala
                   ` (29 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Currently get_lvds_fp_timing() still returns a pointer to the original
data block rather than our copy. Let's convert the data pointer offsets
to be relative to the data block rather than the whole BDB. With that
we can make get_lvds_fp_timing() return a pointer to the copy.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 41 +++++++++++++++++++----
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 2e9f639d092e..000544280c35 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -191,6 +191,29 @@ static const struct {
 	  .min_size = sizeof(struct bdb_generic_dtd), },
 };
 
+/* make the data table offsets relative to the data block */
+static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
+{
+	struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block;
+	u32 offset;
+	int i;
+
+	offset = block_offset(bdb, BDB_LVDS_LFP_DATA);
+
+	for (i = 0; i < 16; i++) {
+		if (ptrs->ptr[i].fp_timing.offset < offset ||
+		    ptrs->ptr[i].dvo_timing.offset < offset ||
+		    ptrs->ptr[i].panel_pnp_id.offset < offset)
+			return false;
+
+		ptrs->ptr[i].fp_timing.offset -= offset;
+		ptrs->ptr[i].dvo_timing.offset -= offset;
+		ptrs->ptr[i].panel_pnp_id.offset -= offset;
+	}
+
+	return true;
+}
+
 static void
 init_bdb_block(struct drm_i915_private *i915,
 	       const void *bdb, enum bdb_block_id section_id,
@@ -217,6 +240,13 @@ init_bdb_block(struct drm_i915_private *i915,
 	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
 		    section_id, block_size, min_size);
 
+	if (section_id == BDB_LVDS_LFP_DATA_PTRS &&
+	    !fixup_lfp_data_ptrs(bdb, entry->data + 3)) {
+		drm_err(&i915->drm, "VBT has malformed LFP data table pointers\n");
+		kfree(entry);
+		return;
+	}
+
 	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
 }
 
@@ -312,22 +342,19 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
  * this function may return NULL if the corresponding entry is invalid
  */
 static const struct lvds_fp_timing *
-get_lvds_fp_timing(const struct bdb_header *bdb,
-		   const struct bdb_lvds_lfp_data *data,
+get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
 		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
 		   int index)
 {
-	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
 	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
 	size_t ofs;
 
 	if (index >= ARRAY_SIZE(ptrs->ptr))
 		return NULL;
 	ofs = ptrs->ptr[index].fp_timing.offset;
-	if (ofs < data_ofs ||
-	    ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
+	if (ofs + sizeof(struct lvds_fp_timing) > data_size)
 		return NULL;
-	return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
+	return (const struct lvds_fp_timing *)((const u8 *)data + ofs);
 }
 
 /* Parse general panel options */
@@ -426,7 +453,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
 		    "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n",
 		    DRM_MODE_ARG(panel_fixed_mode));
 
-	fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
+	fp_timing = get_lvds_fp_timing(lvds_lfp_data,
 				       lvds_lfp_data_ptrs,
 				       panel_type);
 	if (fp_timing) {
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 04/22] drm/i915/bios: Validate LFP data table pointers
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (2 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 03/22] drm/i915/bios: Use the copy of the LFP data table always Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 16:07   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 05/22] drm/i915/bios: Trust the LFP data pointers Ville Syrjala
                   ` (28 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make sure the LFP data table pointers sane. Sensible looking
table entries, everything points correctly into the data block,
etc.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 82 ++++++++++++++++++++++-
 1 file changed, 81 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 000544280c35..cd82ea4de8e1 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -133,6 +133,18 @@ static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
 	return block - bdb;
 }
 
+/* size of the block excluding the header */
+static u32 block_size(const void *bdb, enum bdb_block_id section_id)
+{
+	const void *block;
+
+	block = find_raw_section(bdb, section_id);
+	if (!block)
+		return 0;
+
+	return get_blocksize(block);
+}
+
 struct bdb_block_entry {
 	struct list_head node;
 	enum bdb_block_id section_id;
@@ -191,6 +203,74 @@ static const struct {
 	  .min_size = sizeof(struct bdb_generic_dtd), },
 };
 
+static bool validate_lfp_data_ptrs(const void *bdb,
+				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
+{
+	int fp_timing_size, dvo_timing_size, panel_pnp_id_size;
+	int data_block_size, lfp_data_size;
+	int i;
+
+	data_block_size = block_size(bdb, BDB_LVDS_LFP_DATA);
+	if (data_block_size == 0)
+		return false;
+
+	/* always 3 indicating the presence of fp_timing+dvo_timing+panel_pnp_id */
+	if (ptrs->lvds_entries != 3)
+		return false;
+
+	fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
+	dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
+	panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
+
+	/* fp_timing has variable size */
+	if (fp_timing_size < 32 ||
+	    dvo_timing_size != sizeof(struct lvds_dvo_timing) ||
+	    panel_pnp_id_size != sizeof(struct lvds_pnp_id))
+		return false;
+
+	lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
+	if (16 * lfp_data_size > data_block_size)
+		return false;
+
+	/*
+	 * Except for vlv/chv machines all real VBTs seem to have 6
+	 * unaccounted bytes in the fp_timing table. And it doesn't
+	 * appear to be a really intentional hole as the fp_timing
+	 * 0xffff terminator is always within those 6 missing bytes.
+	 */
+	if (fp_timing_size + dvo_timing_size + panel_pnp_id_size != lfp_data_size &&
+	    fp_timing_size + 6 + dvo_timing_size + panel_pnp_id_size != lfp_data_size)
+		return false;
+
+	if (ptrs->ptr[0].fp_timing.offset + fp_timing_size > ptrs->ptr[0].dvo_timing.offset ||
+	    ptrs->ptr[0].dvo_timing.offset + dvo_timing_size != ptrs->ptr[0].panel_pnp_id.offset ||
+	    ptrs->ptr[0].panel_pnp_id.offset + panel_pnp_id_size != lfp_data_size)
+		return false;
+
+	/* make sure the table entries have uniform size */
+	for (i = 1; i < 16; i++) {
+		if (ptrs->ptr[i].fp_timing.table_size != fp_timing_size ||
+		    ptrs->ptr[i].dvo_timing.table_size != dvo_timing_size ||
+		    ptrs->ptr[i].panel_pnp_id.table_size != panel_pnp_id_size)
+			return false;
+
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
+			return false;
+	}
+
+	/* make sure the tables fit inside the data block */
+	for (i = 0; i < 16; i++) {
+		if (ptrs->ptr[i].fp_timing.offset + fp_timing_size > data_block_size ||
+		    ptrs->ptr[i].dvo_timing.offset + dvo_timing_size > data_block_size ||
+		    ptrs->ptr[i].panel_pnp_id.offset + panel_pnp_id_size > data_block_size)
+			return false;
+	}
+
+	return true;
+}
+
 /* make the data table offsets relative to the data block */
 static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
 {
@@ -211,7 +291,7 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
 		ptrs->ptr[i].panel_pnp_id.offset -= offset;
 	}
 
-	return true;
+	return validate_lfp_data_ptrs(bdb, ptrs);
 }
 
 static void
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 05/22] drm/i915/bios: Trust the LFP data pointers
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (3 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 04/22] drm/i915/bios: Validate LFP data table pointers Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 16:12   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 06/22] drm/i915/bios: Validate the panel_name table Ville Syrjala
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Now that we've sufficiently validated the LFP data pointers we
can trust them.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 60 ++++++-----------------
 1 file changed, 16 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index cd82ea4de8e1..925f521f1f84 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -397,44 +397,19 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
 }
 
 static const struct lvds_dvo_timing *
-get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
-		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
+get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *data,
+		    const struct bdb_lvds_lfp_data_ptrs *ptrs,
 		    int index)
 {
-	/*
-	 * the size of fp_timing varies on the different platform.
-	 * So calculate the DVO timing relative offset in LVDS data
-	 * entry to get the DVO timing entry
-	 */
-
-	int lfp_data_size =
-		lvds_lfp_data_ptrs->ptr[1].dvo_timing.offset -
-		lvds_lfp_data_ptrs->ptr[0].dvo_timing.offset;
-	int dvo_timing_offset =
-		lvds_lfp_data_ptrs->ptr[0].dvo_timing.offset -
-		lvds_lfp_data_ptrs->ptr[0].fp_timing.offset;
-	char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
-
-	return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
+	return (const void *)data + ptrs->ptr[index].dvo_timing.offset;
 }
 
-/* get lvds_fp_timing entry
- * this function may return NULL if the corresponding entry is invalid
- */
 static const struct lvds_fp_timing *
 get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
 		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
 		   int index)
 {
-	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
-	size_t ofs;
-
-	if (index >= ARRAY_SIZE(ptrs->ptr))
-		return NULL;
-	ofs = ptrs->ptr[index].fp_timing.offset;
-	if (ofs + sizeof(struct lvds_fp_timing) > data_size)
-		return NULL;
-	return (const struct lvds_fp_timing *)((const u8 *)data + ofs);
+	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
 }
 
 /* Parse general panel options */
@@ -499,8 +474,7 @@ parse_panel_options(struct drm_i915_private *i915)
 
 /* Try to find integrated panel timing data */
 static void
-parse_lfp_panel_dtd(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_lfp_panel_dtd(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_lfp_data *lvds_lfp_data;
 	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
@@ -536,15 +510,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
 	fp_timing = get_lvds_fp_timing(lvds_lfp_data,
 				       lvds_lfp_data_ptrs,
 				       panel_type);
-	if (fp_timing) {
-		/* check the resolution, just to be sure */
-		if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
-		    fp_timing->y_res == panel_fixed_mode->vdisplay) {
-			i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
-			drm_dbg_kms(&i915->drm,
-				    "VBT initial LVDS value %x\n",
-				    i915->vbt.bios_lvds_val);
-		}
+
+	/* check the resolution, just to be sure */
+	if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
+	    fp_timing->y_res == panel_fixed_mode->vdisplay) {
+		i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
+		drm_dbg_kms(&i915->drm,
+			    "VBT initial LVDS value %x\n",
+			    i915->vbt.bios_lvds_val);
 	}
 }
 
@@ -627,8 +600,7 @@ parse_generic_dtd(struct drm_i915_private *i915)
 }
 
 static void
-parse_panel_dtd(struct drm_i915_private *i915,
-		const struct bdb_header *bdb)
+parse_panel_dtd(struct drm_i915_private *i915)
 {
 	/*
 	 * Older VBTs provided provided DTD information for internal displays
@@ -641,7 +613,7 @@ parse_panel_dtd(struct drm_i915_private *i915,
 	if (i915->vbt.version >= 229)
 		parse_generic_dtd(i915);
 	if (!i915->vbt.lfp_lvds_vbt_mode)
-		parse_lfp_panel_dtd(i915, bdb);
+		parse_lfp_panel_dtd(i915);
 }
 
 static void
@@ -2720,7 +2692,7 @@ void intel_bios_init(struct drm_i915_private *i915)
 	parse_general_features(i915);
 	parse_general_definitions(i915);
 	parse_panel_options(i915);
-	parse_panel_dtd(i915, bdb);
+	parse_panel_dtd(i915);
 	parse_lfp_backlight(i915);
 	parse_sdvo_panel_data(i915);
 	parse_driver_features(i915);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 06/22] drm/i915/bios: Validate the panel_name table
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (4 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 05/22] drm/i915/bios: Trust the LFP data pointers Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 16:14   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing Ville Syrjala
                   ` (26 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

In addition to the fp_timing,dvo_timing,panel_pnp_id tables
there also exists a panel_name table. Unlike the others this
is just one offset+table_size even though there are still 16
actual panel_names in the data block.

The panel_name table made its first appearance somewhere
around VBT version 156-163. The exact version is not known.
But we don't need to know that since we can just check whether
the pointers block has enough room for it or not.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 18 +++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_vbt_defs.h |  5 +++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 925f521f1f84..799c1fe36b23 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -206,7 +206,7 @@ static const struct {
 static bool validate_lfp_data_ptrs(const void *bdb,
 				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
 {
-	int fp_timing_size, dvo_timing_size, panel_pnp_id_size;
+	int fp_timing_size, dvo_timing_size, panel_pnp_id_size, panel_name_size;
 	int data_block_size, lfp_data_size;
 	int i;
 
@@ -221,6 +221,7 @@ static bool validate_lfp_data_ptrs(const void *bdb,
 	fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
 	dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
 	panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
+	panel_name_size = ptrs->panel_name.table_size;
 
 	/* fp_timing has variable size */
 	if (fp_timing_size < 32 ||
@@ -228,6 +229,11 @@ static bool validate_lfp_data_ptrs(const void *bdb,
 	    panel_pnp_id_size != sizeof(struct lvds_pnp_id))
 		return false;
 
+	/* panel_name is not present in old VBTs */
+	if (panel_name_size != 0 &&
+	    panel_name_size != sizeof(struct lvds_lfp_panel_name))
+		return false;
+
 	lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
 	if (16 * lfp_data_size > data_block_size)
 		return false;
@@ -268,6 +274,9 @@ static bool validate_lfp_data_ptrs(const void *bdb,
 			return false;
 	}
 
+	if (ptrs->panel_name.offset + 16 * panel_name_size > data_block_size)
+		return false;
+
 	return true;
 }
 
@@ -291,6 +300,13 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
 		ptrs->ptr[i].panel_pnp_id.offset -= offset;
 	}
 
+	if (ptrs->panel_name.table_size) {
+		if (ptrs->panel_name.offset < offset)
+			return false;
+
+		ptrs->panel_name.offset -= offset;
+	}
+
 	return validate_lfp_data_ptrs(bdb, ptrs);
 }
 
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index d727fcd6cdab..e4a11c3e3f3e 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -737,6 +737,7 @@ struct lvds_lfp_data_ptr {
 struct bdb_lvds_lfp_data_ptrs {
 	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
 	struct lvds_lfp_data_ptr ptr[16];
+	struct lvds_lfp_data_ptr_table panel_name; /* 156-163? */
 } __packed;
 
 /*
@@ -778,6 +779,10 @@ struct bdb_lvds_lfp_data {
 	struct lvds_lfp_data_entry data[16];
 } __packed;
 
+struct lvds_lfp_panel_name {
+	u8 name[13];
+} __packed;
+
 /*
  * Block 43 - LFP Backlight Control Data Block
  */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (5 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 06/22] drm/i915/bios: Validate the panel_name table Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 16:21   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them Ville Syrjala
                   ` (25 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reorder things so that we can parse the entier LFP data block
in one go. For now we just stick to parsing the DTD from it.

Also fix the misleading comment about block 42 being deprecated.
Only the DTD part is deprecated, the rest is still very much needed.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 62 ++++++++++++-----------
 1 file changed, 32 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 799c1fe36b23..f90991cac438 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -488,25 +488,16 @@ parse_panel_options(struct drm_i915_private *i915)
 	}
 }
 
-/* Try to find integrated panel timing data */
 static void
-parse_lfp_panel_dtd(struct drm_i915_private *i915)
+parse_lfp_panel_dtd(struct drm_i915_private *i915,
+		    const struct bdb_lvds_lfp_data *lvds_lfp_data,
+		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs)
 {
-	const struct bdb_lvds_lfp_data *lvds_lfp_data;
-	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
 	const struct lvds_dvo_timing *panel_dvo_timing;
 	const struct lvds_fp_timing *fp_timing;
 	struct drm_display_mode *panel_fixed_mode;
 	int panel_type = i915->vbt.panel_type;
 
-	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
-	if (!lvds_lfp_data)
-		return;
-
-	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
-	if (!lvds_lfp_data_ptrs)
-		return;
-
 	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
 					       lvds_lfp_data_ptrs,
 					       panel_type);
@@ -537,6 +528,24 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915)
 	}
 }
 
+static void
+parse_lfp_data(struct drm_i915_private *i915)
+{
+	const struct bdb_lvds_lfp_data *data;
+	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+
+	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
+	if (!ptrs)
+		return;
+
+	data = find_section(i915, BDB_LVDS_LFP_DATA);
+	if (!data)
+		return;
+
+	if (!i915->vbt.lfp_lvds_vbt_mode)
+		parse_lfp_panel_dtd(i915, data, ptrs);
+}
+
 static void
 parse_generic_dtd(struct drm_i915_private *i915)
 {
@@ -615,23 +624,6 @@ parse_generic_dtd(struct drm_i915_private *i915)
 	i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
 }
 
-static void
-parse_panel_dtd(struct drm_i915_private *i915)
-{
-	/*
-	 * Older VBTs provided provided DTD information for internal displays
-	 * through the "LFP panel DTD" block (42).  As of VBT revision 229,
-	 * that block is now deprecated and DTD information should be provided
-	 * via a newer "generic DTD" block (58).  Just to be safe, we'll
-	 * try the new generic DTD block first on VBT >= 229, but still fall
-	 * back to trying the old LFP block if that fails.
-	 */
-	if (i915->vbt.version >= 229)
-		parse_generic_dtd(i915);
-	if (!i915->vbt.lfp_lvds_vbt_mode)
-		parse_lfp_panel_dtd(i915);
-}
-
 static void
 parse_lfp_backlight(struct drm_i915_private *i915)
 {
@@ -2708,7 +2700,17 @@ void intel_bios_init(struct drm_i915_private *i915)
 	parse_general_features(i915);
 	parse_general_definitions(i915);
 	parse_panel_options(i915);
-	parse_panel_dtd(i915);
+	/*
+	 * Older VBTs provided DTD information for internal displays through
+	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
+	 * DTD information should be provided via a newer "generic DTD"
+	 * block (58).  Just to be safe, we'll try the new generic DTD block
+	 * first on VBT >= 229, but still fall back to trying the old LFP
+	 * block if that fails.
+	 */
+	if (i915->vbt.version >= 229)
+		parse_generic_dtd(i915);
+	parse_lfp_data(i915);
 	parse_lfp_backlight(i915);
 	parse_sdvo_panel_data(i915);
 	parse_driver_features(i915);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (6 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-06 13:39   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 09/22] drm/i915/bios: Get access to the tail end of the LFP data block Ville Syrjala
                   ` (24 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Modern VBTs no longer contain the LFP data table pointers
block (41). We are expecting to have one in order to be able
to parse the LFP data block (42), so let's make one up.

Since the fp_timing table has variable size we must somehow
determine its size. Rather than just hardcode it we look for
the terminator bytes (0xffff) to figure out where each table
entry starts. dvo_timing, panel_pnp_id, and panel_name are
expected to have fixed size.

This has been observed on various machines, eg. TGL with BDB
version 240, CML with BDB version 231, etc. The most recent
VBT I've observed that still had block 41 had BDB version
228. So presumably the cutoff (if an exact cutoff even exists)
is somewhere around BDB version 229-231.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 133 +++++++++++++++++++++-
 1 file changed, 132 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index f90991cac438..8fe76d2546e3 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -310,16 +310,143 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
 	return validate_lfp_data_ptrs(bdb, ptrs);
 }
 
+static const void *find_fp_timing_terminator(const u8 *data, int size)
+{
+	int i;
+
+	if (!data)
+		return NULL;
+
+	for (i = 0; i < size - 1; i++) {
+		if (data[i] == 0xff && data[i+1] == 0xff)
+			return &data[i];
+	}
+
+	return NULL;
+}
+
+static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
+			     int table_size, int total_size)
+{
+	if (total_size < table_size)
+		return total_size;
+
+	table->table_size = table_size;
+	table->offset = total_size - table_size;
+
+	return total_size - table_size;
+}
+
+static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
+			      const struct lvds_lfp_data_ptr_table *prev,
+			      int size)
+{
+	next->table_size = prev->table_size;
+	next->offset = prev->offset + size;
+}
+
+static void *generate_lfp_data_ptrs(const void *bdb)
+{
+	int i, size, table_size, block_size, offset;
+	const void *t0, *t1, *block;
+	struct bdb_lvds_lfp_data_ptrs *ptrs;
+	void *ptrs_block;
+
+	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
+	if (!block)
+		return NULL;
+
+	block_size = get_blocksize(block);
+
+	size = block_size;
+	t0 = find_fp_timing_terminator(block, size);
+
+	size -= t0 - block - 2;
+	t1 = find_fp_timing_terminator(t0 + 2, size);
+
+	if (!t0 || !t1)
+		return NULL;
+
+	size = t1 - t0;
+	if (size * 16 > block_size)
+		return NULL;
+
+	ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
+	if (!ptrs_block)
+		return NULL;
+
+	*(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS;
+	*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
+	ptrs = ptrs_block + 3;
+
+	table_size = sizeof(struct lvds_pnp_id);
+	size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
+
+	table_size = sizeof(struct lvds_dvo_timing);
+	size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
+
+	table_size = t0 - block + 2;
+	size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
+
+	if (ptrs->ptr[0].fp_timing.table_size)
+		ptrs->lvds_entries++;
+	if (ptrs->ptr[0].dvo_timing.table_size)
+		ptrs->lvds_entries++;
+	if (ptrs->ptr[0].panel_pnp_id.table_size)
+		ptrs->lvds_entries++;
+
+	if (size != 0 || ptrs->lvds_entries != 3) {
+		kfree(ptrs);
+		return NULL;
+	}
+
+	size = t1 - t0;
+	for (i = 1; i < 16; i++) {
+		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
+		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
+		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
+	}
+
+	size = t1 - t0;
+	table_size = sizeof(struct lvds_lfp_panel_name);
+
+	if (16 * (size + table_size) <= block_size) {
+		ptrs->panel_name.table_size = table_size;
+		ptrs->panel_name.offset = size * 16;
+	}
+
+	offset = block - bdb;
+
+	for (i = 0; i < 16; i++) {
+		ptrs->ptr[i].fp_timing.offset += offset;
+		ptrs->ptr[i].dvo_timing.offset += offset;
+		ptrs->ptr[i].panel_pnp_id.offset += offset;
+	}
+
+	if (ptrs->panel_name.table_size)
+		ptrs->panel_name.offset += offset;
+
+	return ptrs;
+}
+
 static void
 init_bdb_block(struct drm_i915_private *i915,
 	       const void *bdb, enum bdb_block_id section_id,
 	       size_t min_size)
 {
 	struct bdb_block_entry *entry;
+	void *temp_block = NULL;
 	const void *block;
 	size_t block_size;
 
 	block = find_raw_section(bdb, section_id);
+
+	/* Modern VBTs lack the LFP data table pointers block, make one up */
+	if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) {
+		drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
+		temp_block = generate_lfp_data_ptrs(bdb);
+		block = temp_block;
+	}
 	if (!block)
 		return;
 
@@ -327,12 +454,16 @@ init_bdb_block(struct drm_i915_private *i915,
 
 	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
 			GFP_KERNEL);
-	if (!entry)
+	if (!entry) {
+		kfree(temp_block);
 		return;
+	}
 
 	entry->section_id = section_id;
 	memcpy(entry->data, block - 3, block_size + 3);
 
+	kfree(temp_block);
+
 	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
 		    section_id, block_size, min_size);
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 09/22] drm/i915/bios: Get access to the tail end of the LFP data block
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (7 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-06 13:40   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 10/22] drm/i915/bios: Assume panel_type==0 if the VBT has bogus data Ville Syrjala
                   ` (23 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We need to start parsing stuff from the tail end of the LFP data block.
This is made awkward by the fact that the fp_timing table has variable
size. So we must use a bit more finesse to get the tail end, and to
make sure we allocate enough memory for it to make sure our struct
representation fits.

v2: Rebase due to the preallocation of BDB blocks

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 39 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_vbt_defs.h | 17 ++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 8fe76d2546e3..01e0b12e2dea 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -188,7 +188,7 @@ static const struct {
 	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
 	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
 	{ .section_id = BDB_LVDS_LFP_DATA,
-	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
+	  .min_size = 0, /* special case */ },
 	{ .section_id = BDB_LVDS_BACKLIGHT,
 	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
 	{ .section_id = BDB_LFP_POWER,
@@ -203,6 +203,23 @@ static const struct {
 	  .min_size = sizeof(struct bdb_generic_dtd), },
 };
 
+static size_t lfp_data_min_size(struct drm_i915_private *i915)
+{
+	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+	size_t size;
+
+	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
+	if (!ptrs)
+		return 0;
+
+	size = sizeof(struct bdb_lvds_lfp_data);
+	if (ptrs->panel_name.table_size)
+		size = max(size, ptrs->panel_name.offset +
+			   sizeof(struct bdb_lvds_lfp_data_tail));
+
+	return size;
+}
+
 static bool validate_lfp_data_ptrs(const void *bdb,
 				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
 {
@@ -486,6 +503,9 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
 		enum bdb_block_id section_id = bdb_blocks[i].section_id;
 		size_t min_size = bdb_blocks[i].min_size;
 
+		if (section_id == BDB_LVDS_LFP_DATA)
+			min_size = lfp_data_min_size(i915);
+
 		drm_WARN(&i915->drm, min_size == 0,
 			 "Block %d min_size is zero\n", section_id);
 
@@ -559,6 +579,16 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
 	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
 }
 
+static const struct bdb_lvds_lfp_data_tail *
+get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
+		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
+{
+	if (ptrs->panel_name.table_size)
+		return (const void *)data + ptrs->panel_name.offset;
+	else
+		return NULL;
+}
+
 /* Parse general panel options */
 static void
 parse_panel_options(struct drm_i915_private *i915)
@@ -663,6 +693,7 @@ static void
 parse_lfp_data(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_lfp_data *data;
+	const struct bdb_lvds_lfp_data_tail *tail;
 	const struct bdb_lvds_lfp_data_ptrs *ptrs;
 
 	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
@@ -675,6 +706,12 @@ parse_lfp_data(struct drm_i915_private *i915)
 
 	if (!i915->vbt.lfp_lvds_vbt_mode)
 		parse_lfp_panel_dtd(i915, data, ptrs);
+
+	tail = get_lfp_data_tail(data, ptrs);
+	if (!tail)
+		return;
+
+	(void)tail;
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index e4a11c3e3f3e..64551d206aeb 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -783,6 +783,23 @@ struct lvds_lfp_panel_name {
 	u8 name[13];
 } __packed;
 
+struct lvds_lfp_black_border {
+	u8 top; /*  227 */
+	u8 bottom; /*  227 */
+	u8 left; /* 238 */
+	u8 right; /* 238 */
+} __packed;
+
+struct bdb_lvds_lfp_data_tail {
+	struct lvds_lfp_panel_name panel_name[16]; /* 156-163? */
+	u16 scaling_enable; /* 187 */
+	u8 seamless_drrs_min_refresh_rate[16]; /* 188 */
+	u8 pixel_overlap_count[16]; /* 208 */
+	struct lvds_lfp_black_border black_border[16]; /* 227 */
+	u16 dual_lfp_port_sync_enable; /* 231 */
+	u16 gpu_dithering_for_banding_artifacts; /* 245 */
+} __packed;
+
 /*
  * Block 43 - LFP Backlight Control Data Block
  */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 10/22] drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (8 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 09/22] drm/i915/bios: Get access to the tail end of the LFP data block Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 17:11   ` Jani Nikula
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 11/22] drm/i915/bios: Split parse_driver_features() into two parts Ville Syrjala
                   ` (22 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Just assume panel_type==0 always if the VBT gives us bogus data.
We actually already do this everywhere else except in
parse_panel_options() since we just leave i915->vbt.panel_type
zeroed. This also seems to be what Windows does.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 01e0b12e2dea..502d4c679198 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -613,13 +613,14 @@ parse_panel_options(struct drm_i915_private *i915)
 	} else {
 		if (lvds_options->panel_type > 0xf) {
 			drm_dbg_kms(&i915->drm,
-				    "Invalid VBT panel type 0x%x\n",
+				    "Invalid VBT panel type 0x%x, assuming 0\n",
 				    lvds_options->panel_type);
-			return;
+			panel_type = 0;
+		} else {
+			panel_type = lvds_options->panel_type;
+			drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n",
+				    panel_type);
 		}
-		panel_type = lvds_options->panel_type;
-		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n",
-			    panel_type);
 	}
 
 	i915->vbt.panel_type = panel_type;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 11/22] drm/i915/bios: Split parse_driver_features() into two parts
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (9 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 10/22] drm/i915/bios: Assume panel_type==0 if the VBT has bogus data Ville Syrjala
@ 2022-04-05 17:33 ` Ville Syrjala
  2022-04-07 17:13   ` Jani Nikula
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts Ville Syrjala
                   ` (21 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:33 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We use the "driver features" block for two different kinds
of data: global data, and per panel data. Split the function
into two parts along that line so that we can start doing the
parsing in two different locations.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 502d4c679198..1a7f1aa79827 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1097,6 +1097,16 @@ parse_driver_features(struct drm_i915_private *i915)
 		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
 			i915->vbt.int_lvds_support = 0;
 	}
+}
+
+static void
+parse_panel_driver_features(struct drm_i915_private *i915)
+{
+	const struct bdb_driver_features *driver;
+
+	driver = find_section(i915, BDB_DRIVER_FEATURES);
+	if (!driver)
+		return;
 
 	if (i915->vbt.version < 228) {
 		drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
@@ -2883,6 +2893,7 @@ void intel_bios_init(struct drm_i915_private *i915)
 	parse_lfp_backlight(i915);
 	parse_sdvo_panel_data(i915);
 	parse_driver_features(i915);
+	parse_panel_driver_features(i915);
 	parse_power_conservation_features(i915);
 	parse_edp(i915);
 	parse_psr(i915);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (10 preceding siblings ...)
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 11/22] drm/i915/bios: Split parse_driver_features() into two parts Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-07 17:23   ` Jani Nikula
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 13/22] drm/i915/pps: Split PPS init+sanitize in two Ville Syrjala
                   ` (20 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Parsing the panel specific data from VBT is currently happening
too early. Split the whole thing into global vs. panel specific
parts so that we can start doing the panel specific parsing at
a later time.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c    | 50 +++++++++++++-------
 drivers/gpu/drm/i915/display/intel_bios.h    |  1 +
 drivers/gpu/drm/i915/display/intel_display.c |  1 +
 3 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 1a7f1aa79827..da2b1932e10d 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -723,6 +723,9 @@ parse_generic_dtd(struct drm_i915_private *i915)
 	struct drm_display_mode *panel_fixed_mode;
 	int num_dtd;
 
+	if (i915->vbt.lfp_lvds_vbt_mode)
+		return;
+
 	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
 	if (!generic_dtd)
 		return;
@@ -891,6 +894,9 @@ parse_sdvo_panel_data(struct drm_i915_private *i915)
 	struct drm_display_mode *panel_fixed_mode;
 	int index;
 
+	if (i915->vbt.sdvo_lvds_vbt_mode)
+		return;
+
 	index = i915->params.vbt_sdvo_panel_type;
 	if (index == -2) {
 		drm_dbg_kms(&i915->drm,
@@ -1419,6 +1425,9 @@ parse_mipi_config(struct drm_i915_private *i915)
 	int panel_type = i915->vbt.panel_type;
 	enum port port;
 
+	if (i915->vbt.dsi.config)
+		return;
+
 	/* parse MIPI blocks only if LFP type is MIPI */
 	if (!intel_bios_is_dsi_present(i915, &port))
 		return;
@@ -1739,6 +1748,9 @@ parse_mipi_sequence(struct drm_i915_private *i915)
 	u8 *data;
 	int index = 0;
 
+	if (i915->vbt.dsi.data)
+		return;
+
 	/* Only our generic panel driver uses the sequence block. */
 	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
 		return;
@@ -2878,6 +2890,27 @@ void intel_bios_init(struct drm_i915_private *i915)
 	/* Grab useful general definitions */
 	parse_general_features(i915);
 	parse_general_definitions(i915);
+	parse_driver_features(i915);
+
+	/* Depends on child device list */
+	parse_compression_parameters(i915);
+
+out:
+	if (!vbt) {
+		drm_info(&i915->drm,
+			 "Failed to find VBIOS tables (VBT)\n");
+		init_vbt_missing_defaults(i915);
+	}
+
+	/* Further processing on pre-parsed or generated child device data */
+	parse_sdvo_device_mapping(i915);
+	parse_ddi_ports(i915);
+
+	kfree(oprom_vbt);
+}
+
+void intel_bios_init_panel(struct drm_i915_private *i915)
+{
 	parse_panel_options(i915);
 	/*
 	 * Older VBTs provided DTD information for internal displays through
@@ -2892,29 +2925,12 @@ void intel_bios_init(struct drm_i915_private *i915)
 	parse_lfp_data(i915);
 	parse_lfp_backlight(i915);
 	parse_sdvo_panel_data(i915);
-	parse_driver_features(i915);
 	parse_panel_driver_features(i915);
 	parse_power_conservation_features(i915);
 	parse_edp(i915);
 	parse_psr(i915);
 	parse_mipi_config(i915);
 	parse_mipi_sequence(i915);
-
-	/* Depends on child device list */
-	parse_compression_parameters(i915);
-
-out:
-	if (!vbt) {
-		drm_info(&i915->drm,
-			 "Failed to find VBIOS tables (VBT)\n");
-		init_vbt_missing_defaults(i915);
-	}
-
-	/* Further processing on pre-parsed or generated child device data */
-	parse_sdvo_device_mapping(i915);
-	parse_ddi_ports(i915);
-
-	kfree(oprom_vbt);
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index 4709c4d29805..c744d75fa435 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -230,6 +230,7 @@ struct mipi_pps_data {
 } __packed;
 
 void intel_bios_init(struct drm_i915_private *dev_priv);
+void intel_bios_init_panel(struct drm_i915_private *dev_priv);
 void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
 bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index eee185ed41c3..4ece4e7d0296 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9650,6 +9650,7 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
 	}
 
 	intel_bios_init(i915);
+	intel_bios_init_panel(i915);
 
 	ret = intel_vga_register(i915);
 	if (ret)
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 13/22] drm/i915/pps: Split PPS init+sanitize in two
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (11 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 14/22] drm/i915/pps: Reinit PPS delays after VBT has been fully parsed Ville Syrjala
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Split the PPS init to something we do at the start of the eDP
probe and a second part we do at the end.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  |  2 ++
 drivers/gpu/drm/i915/display/intel_pps.c | 30 ++++++++++++++++++++----
 drivers/gpu/drm/i915/display/intel_pps.h |  1 +
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 972c9ed46829..7249b988592d 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5222,6 +5222,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 
 	intel_edp_add_properties(intel_dp);
 
+	intel_pps_init_late(intel_dp);
+
 	return true;
 
 out_vdd_off:
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 64bd4ca0edd4..6ab8d971901b 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -1050,7 +1050,7 @@ void vlv_pps_init(struct intel_encoder *encoder,
 	pps_init_registers(intel_dp, true);
 }
 
-static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
+static void pps_vdd_init(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -1071,8 +1071,6 @@ static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
 	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref);
 	intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
 							    intel_aux_power_domain(dig_port));
-
-	edp_panel_vdd_schedule_off(intel_dp);
 }
 
 bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp)
@@ -1366,18 +1364,40 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
 
 		pps_init_delays(intel_dp);
 		pps_init_registers(intel_dp, false);
+		pps_vdd_init(intel_dp);
 
-		intel_pps_vdd_sanitize(intel_dp);
+		if (edp_have_panel_vdd(intel_dp))
+			edp_panel_vdd_schedule_off(intel_dp);
 	}
 }
 
 void intel_pps_init(struct intel_dp *intel_dp)
 {
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	intel_wakeref_t wakeref;
+
 	INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work);
 
 	pps_init_timestamps(intel_dp);
 
-	intel_pps_encoder_reset(intel_dp);
+	with_intel_pps_lock(intel_dp, wakeref) {
+		if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+			vlv_initial_power_sequencer_setup(intel_dp);
+
+		pps_init_delays(intel_dp);
+		pps_init_registers(intel_dp, false);
+		pps_vdd_init(intel_dp);
+	}
+}
+
+void intel_pps_init_late(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	with_intel_pps_lock(intel_dp, wakeref) {
+		if (edp_have_panel_vdd(intel_dp))
+			edp_panel_vdd_schedule_off(intel_dp);
+	}
 }
 
 void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index e64144659d31..a3a56f903f26 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -41,6 +41,7 @@ bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp);
 void intel_pps_wait_power_cycle(struct intel_dp *intel_dp);
 
 void intel_pps_init(struct intel_dp *intel_dp);
+void intel_pps_init_late(struct intel_dp *intel_dp);
 void intel_pps_encoder_reset(struct intel_dp *intel_dp);
 void intel_pps_reset_all(struct drm_i915_private *i915);
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 14/22] drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (12 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 13/22] drm/i915/pps: Split PPS init+sanitize in two Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 15/22] drm/i915/bios: Do panel specific VBT parsing later Ville Syrjala
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

During the eDP probe we may not yet know the panel_type used
to index the VBT panel tables. So the initial eDP probe will have
to be done without that, and thus we won't yet have the PPS delays
from the VBT. Once the VBT has been fully parse we should reinit
the PPS delays to make sure it's fully accounted for.

TODO: I wonder if we should do the eDP probe with some super safe
PPS delayes (eg. max of all VBT PPS delays) just to make sure we
don't violate the timings. Though typically the VBIOS/GOP do leave
VDD enabled after boot in which case we don't actually have to care
about the delays at all.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_pps.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 6ab8d971901b..140191290e85 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -1395,6 +1395,11 @@ void intel_pps_init_late(struct intel_dp *intel_dp)
 	intel_wakeref_t wakeref;
 
 	with_intel_pps_lock(intel_dp, wakeref) {
+		/* Reinit delays after per-panel info has been parsed from VBT */
+		memset(&intel_dp->pps.pps_delays, 0, sizeof(intel_dp->pps.pps_delays));
+		pps_init_delays(intel_dp);
+		pps_init_registers(intel_dp, false);
+
 		if (edp_have_panel_vdd(intel_dp))
 			edp_panel_vdd_schedule_off(intel_dp);
 	}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 15/22] drm/i915/bios: Do panel specific VBT parsing later
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (13 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 14/22] drm/i915/pps: Reinit PPS delays after VBT has been fully parsed Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-06 19:05   ` [Intel-gfx] [PATCH v4 " Ville Syrjala
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 16/22] drm/i915/bios: Extract get_panel_type() Ville Syrjala
                   ` (17 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the panel specific VBT parsing to happen during the
output probing stage. Needs to be done because the VBT
parsing will need to look at the EDID to determine
the correct panel_type on some machines.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/icl_dsi.c       | 2 ++
 drivers/gpu/drm/i915/display/intel_display.c | 1 -
 drivers/gpu/drm/i915/display/intel_dp.c      | 2 ++
 drivers/gpu/drm/i915/display/intel_lvds.c    | 2 ++
 drivers/gpu/drm/i915/display/intel_sdvo.c    | 3 +++
 drivers/gpu/drm/i915/display/vlv_dsi.c       | 2 ++
 6 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 084cc51d1c41..688176d4a54a 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -2048,6 +2048,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
 	/* attach connector to encoder */
 	intel_connector_attach_encoder(intel_connector, encoder);
 
+	intel_bios_init_panel(dev_priv);
+
 	mutex_lock(&dev->mode_config.mutex);
 	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
 	mutex_unlock(&dev->mode_config.mutex);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 4ece4e7d0296..eee185ed41c3 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9650,7 +9650,6 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
 	}
 
 	intel_bios_init(i915);
-	intel_bios_init_panel(i915);
 
 	ret = intel_vga_register(i915);
 	if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 7249b988592d..a1b5d7f5388b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5179,6 +5179,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	intel_connector->edid = edid;
 
+	intel_bios_init_panel(dev_priv);
+
 	intel_panel_add_edid_fixed_modes(intel_connector,
 					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
 
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index e8478161f8b9..554badf041f2 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -967,6 +967,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
 	}
 	intel_connector->edid = edid;
 
+	intel_bios_init_panel(dev_priv);
+
 	/* Try EDID first */
 	intel_panel_add_edid_fixed_modes(intel_connector,
 					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index ab88d8b783e6..661a1057a073 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2868,6 +2868,7 @@ static bool
 intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 {
 	struct drm_encoder *encoder = &intel_sdvo->base.base;
+	struct drm_i915_private *i915 = to_i915(encoder->dev);
 	struct drm_connector *connector;
 	struct intel_connector *intel_connector;
 	struct intel_sdvo_connector *intel_sdvo_connector;
@@ -2899,6 +2900,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
 		goto err;
 
+	intel_bios_init_panel(i915);
+
 	/*
 	 * Fetch modes from VBT. For SDVO prefer the VBT mode since some
 	 * SDVO->LVDS transcoders can't cope with the EDID mode.
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 1954f07f0d3e..7849836355f9 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1944,6 +1944,8 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
 		intel_dsi->dsi_hosts[port] = host;
 	}
 
+	intel_bios_init_panel(dev_priv);
+
 	if (!intel_dsi_vbt_init(intel_dsi, MIPI_DSI_GENERIC_PANEL_ID)) {
 		drm_dbg_kms(&dev_priv->drm, "no device found\n");
 		goto err;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 16/22] drm/i915/bios: Extract get_panel_type()
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (14 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 15/22] drm/i915/bios: Do panel specific VBT parsing later Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-07 17:26   ` Jani Nikula
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code Ville Syrjala
                   ` (16 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Pull the code to determine the panel type into its own set of
sane functions.

v2: rebase

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 58 +++++++++++++++--------
 1 file changed, 39 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index da2b1932e10d..26839263abf0 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -589,6 +589,44 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
 		return NULL;
 }
 
+static int vbt_panel_type(struct drm_i915_private *i915)
+{
+	const struct bdb_lvds_options *lvds_options;
+
+	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
+	if (!lvds_options)
+		return -1;
+
+	if (lvds_options->panel_type > 0xf) {
+		drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n",
+			    lvds_options->panel_type);
+		return -1;
+	}
+
+	return lvds_options->panel_type;
+}
+
+static int get_panel_type(struct drm_i915_private *i915)
+{
+	int ret;
+
+	ret = intel_opregion_get_panel_type(i915);
+	if (ret >= 0) {
+		drm_WARN_ON(&i915->drm, ret > 0xf);
+		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n", ret);
+		return ret;
+	}
+
+	ret = vbt_panel_type(i915);
+	if (ret >= 0) {
+		drm_WARN_ON(&i915->drm, ret > 0xf);
+		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n", ret);
+		return ret;
+	}
+
+	return 0; /* fallback */
+}
+
 /* Parse general panel options */
 static void
 parse_panel_options(struct drm_i915_private *i915)
@@ -596,7 +634,6 @@ parse_panel_options(struct drm_i915_private *i915)
 	const struct bdb_lvds_options *lvds_options;
 	int panel_type;
 	int drrs_mode;
-	int ret;
 
 	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
@@ -604,24 +641,7 @@ parse_panel_options(struct drm_i915_private *i915)
 
 	i915->vbt.lvds_dither = lvds_options->pixel_dither;
 
-	ret = intel_opregion_get_panel_type(i915);
-	if (ret >= 0) {
-		drm_WARN_ON(&i915->drm, ret > 0xf);
-		panel_type = ret;
-		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n",
-			    panel_type);
-	} else {
-		if (lvds_options->panel_type > 0xf) {
-			drm_dbg_kms(&i915->drm,
-				    "Invalid VBT panel type 0x%x, assuming 0\n",
-				    lvds_options->panel_type);
-			panel_type = 0;
-		} else {
-			panel_type = lvds_options->panel_type;
-			drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n",
-				    panel_type);
-		}
-	}
+	panel_type = get_panel_type(i915);
 
 	i915->vbt.panel_type = panel_type;
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (15 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 16/22] drm/i915/bios: Extract get_panel_type() Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-07 17:49   ` Jani Nikula
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 18/22] drm/i915/bios: Determine panel type via PNPID match Ville Syrjala
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make the panel type code a bit more abstract along the
lines of the source of the panel type. For the moment
we have three classes: OpRegion, VBT, fallback.
Well introduce another one shortly.

We can now also print out all the different panel types,
and indicate which one we ultimately selected. Could help
with debugging.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 47 ++++++++++++++++-------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 26839263abf0..feef5aa97398 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -606,25 +606,46 @@ static int vbt_panel_type(struct drm_i915_private *i915)
 	return lvds_options->panel_type;
 }
 
+enum panel_type {
+	PANEL_TYPE_OPREGION,
+	PANEL_TYPE_VBT,
+	PANEL_TYPE_FALLBACK,
+};
+
 static int get_panel_type(struct drm_i915_private *i915)
 {
-	int ret;
+	struct {
+		const char *name;
+		int panel_type;
+	} panel_types[] = {
+		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
+		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
+		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
+	};
+	int i;
 
-	ret = intel_opregion_get_panel_type(i915);
-	if (ret >= 0) {
-		drm_WARN_ON(&i915->drm, ret > 0xf);
-		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n", ret);
-		return ret;
-	}
+	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
+	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);
+
+	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
+		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);
 
-	ret = vbt_panel_type(i915);
-	if (ret >= 0) {
-		drm_WARN_ON(&i915->drm, ret > 0xf);
-		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n", ret);
-		return ret;
+		if (panel_types[i].panel_type >= 0)
+			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
+				    panel_types[i].name, panel_types[i].panel_type);
 	}
 
-	return 0; /* fallback */
+	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
+		i = PANEL_TYPE_OPREGION;
+	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
+		i = PANEL_TYPE_VBT;
+	else
+		i = PANEL_TYPE_FALLBACK;
+
+	drm_dbg_kms(&i915->drm, "Selected panel type (%s): %d\n",
+		    panel_types[i].name, panel_types[i].panel_type);
+
+	return panel_types[i].panel_type;
 }
 
 /* Parse general panel options */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 18/22] drm/i915/bios: Determine panel type via PNPID match
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (16 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-06 19:09   ` [Intel-gfx] [PATCH v4 " Ville Syrjala
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 19/22] drm/i915/bios: Parse the seamless DRRS min refresh rate Ville Syrjala
                   ` (14 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Apparently when the VBT panel_type==0xff we should trawl through
the PNPID table and check for a match against the EDID. If a
match is found the index gives us the panel_type.

Tried to match the Windows behaviour here with first looking
for an exact match, and if one isn't found we fall back to
looking for a match w/o the mfg year/week.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5545
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/icl_dsi.c    |  2 +-
 drivers/gpu/drm/i915/display/intel_bios.c | 82 ++++++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_bios.h |  4 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  2 +-
 drivers/gpu/drm/i915/display/intel_lvds.c |  2 +-
 drivers/gpu/drm/i915/display/intel_sdvo.c |  2 +-
 drivers/gpu/drm/i915/display/vlv_dsi.c    |  2 +-
 7 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 688176d4a54a..49715485a3a6 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -2048,7 +2048,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
 	/* attach connector to encoder */
 	intel_connector_attach_encoder(intel_connector, encoder);
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, NULL);
 
 	mutex_lock(&dev->mode_config.mutex);
 	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index feef5aa97398..cfdfe91d4ccf 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -579,6 +579,14 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
 	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
 }
 
+static const struct lvds_pnp_id *
+get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data,
+		const struct bdb_lvds_lfp_data_ptrs *ptrs,
+		int index)
+{
+	return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset;
+}
+
 static const struct bdb_lvds_lfp_data_tail *
 get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
 		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
@@ -589,6 +597,52 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
 		return NULL;
 }
 
+static int pnp_id_panel_type(struct drm_i915_private *i915,
+			     const struct edid *edid)
+{
+	const struct bdb_lvds_lfp_data *data;
+	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+	const struct lvds_pnp_id *edid_id;
+	struct lvds_pnp_id edid_id_nodate;
+	int i, best = -1;
+
+	if (!edid)
+		return -1;
+
+	edid_id = (const void *)&edid->mfg_id[0];
+
+	edid_id_nodate = *edid_id;
+	edid_id_nodate.mfg_week = 0;
+	edid_id_nodate.mfg_year = 0;
+
+	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
+	if (!ptrs)
+		return -1;
+
+	data = find_section(i915, BDB_LVDS_LFP_DATA);
+	if (!data)
+		return -1;
+
+	for (i = 0; i < 16; i++) {
+		const struct lvds_pnp_id *vbt_id =
+			get_lvds_pnp_id(data, ptrs, i);
+
+		/* full match? */
+		if (!memcmp(vbt_id, edid_id, sizeof(*vbt_id)))
+			return i;
+
+		/*
+		 * Accept a match w/o date if no full match is found,
+		 * and the VBT entry does not specify a date.
+		 */
+		if (best < 0 &&
+		    !memcmp(vbt_id, &edid_id_nodate, sizeof(*vbt_id)))
+			best = i;
+	}
+
+	return best;
+}
+
 static int vbt_panel_type(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_options *lvds_options;
@@ -597,7 +651,8 @@ static int vbt_panel_type(struct drm_i915_private *i915)
 	if (!lvds_options)
 		return -1;
 
-	if (lvds_options->panel_type > 0xf) {
+	if (lvds_options->panel_type > 0xf &&
+	    lvds_options->panel_type != 0xff) {
 		drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n",
 			    lvds_options->panel_type);
 		return -1;
@@ -609,10 +664,12 @@ static int vbt_panel_type(struct drm_i915_private *i915)
 enum panel_type {
 	PANEL_TYPE_OPREGION,
 	PANEL_TYPE_VBT,
+	PANEL_TYPE_PNPID,
 	PANEL_TYPE_FALLBACK,
 };
 
-static int get_panel_type(struct drm_i915_private *i915)
+static int get_panel_type(struct drm_i915_private *i915,
+			  const struct edid *edid)
 {
 	struct {
 		const char *name;
@@ -620,15 +677,18 @@ static int get_panel_type(struct drm_i915_private *i915)
 	} panel_types[] = {
 		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
 		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
+		[PANEL_TYPE_PNPID] = { .name = "PNPID", .panel_type = -1, },
 		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
 	};
 	int i;
 
 	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
 	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);
+	panel_types[PANEL_TYPE_PNPID].panel_type = pnp_id_panel_type(i915, edid);
 
 	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
-		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);
+		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf &&
+			    panel_types[i].panel_type != 0xff);
 
 		if (panel_types[i].panel_type >= 0)
 			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
@@ -637,7 +697,11 @@ static int get_panel_type(struct drm_i915_private *i915)
 
 	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
 		i = PANEL_TYPE_OPREGION;
-	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
+	else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
+		 panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
+		i = PANEL_TYPE_PNPID;
+	else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
+		 panel_types[PANEL_TYPE_VBT].panel_type >= 0)
 		i = PANEL_TYPE_VBT;
 	else
 		i = PANEL_TYPE_FALLBACK;
@@ -650,7 +714,8 @@ static int get_panel_type(struct drm_i915_private *i915)
 
 /* Parse general panel options */
 static void
-parse_panel_options(struct drm_i915_private *i915)
+parse_panel_options(struct drm_i915_private *i915,
+		    const struct edid *edid)
 {
 	const struct bdb_lvds_options *lvds_options;
 	int panel_type;
@@ -662,7 +727,7 @@ parse_panel_options(struct drm_i915_private *i915)
 
 	i915->vbt.lvds_dither = lvds_options->pixel_dither;
 
-	panel_type = get_panel_type(i915);
+	panel_type = get_panel_type(i915, edid);
 
 	i915->vbt.panel_type = panel_type;
 
@@ -2950,9 +3015,10 @@ void intel_bios_init(struct drm_i915_private *i915)
 	kfree(oprom_vbt);
 }
 
-void intel_bios_init_panel(struct drm_i915_private *i915)
+void intel_bios_init_panel(struct drm_i915_private *i915,
+			   const struct edid *edid)
 {
-	parse_panel_options(i915);
+	parse_panel_options(i915, edid);
 	/*
 	 * Older VBTs provided DTD information for internal displays through
 	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index c744d75fa435..be6d57bd0f5a 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -33,6 +33,7 @@
 #include <linux/types.h>
 
 struct drm_i915_private;
+struct edid;
 struct intel_bios_encoder_data;
 struct intel_crtc_state;
 struct intel_encoder;
@@ -230,7 +231,8 @@ struct mipi_pps_data {
 } __packed;
 
 void intel_bios_init(struct drm_i915_private *dev_priv);
-void intel_bios_init_panel(struct drm_i915_private *dev_priv);
+void intel_bios_init_panel(struct drm_i915_private *dev_priv,
+			   const struct edid *edid);
 void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
 bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a1b5d7f5388b..41ac55a700e9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5179,7 +5179,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	intel_connector->edid = edid;
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
 
 	intel_panel_add_edid_fixed_modes(intel_connector,
 					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 554badf041f2..660bb95f2bf7 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -967,7 +967,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
 	}
 	intel_connector->edid = edid;
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
 
 	/* Try EDID first */
 	intel_panel_add_edid_fixed_modes(intel_connector,
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index 661a1057a073..25195bc1edca 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2900,7 +2900,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
 		goto err;
 
-	intel_bios_init_panel(i915);
+	intel_bios_init_panel(i915, NULL);
 
 	/*
 	 * Fetch modes from VBT. For SDVO prefer the VBT mode since some
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 7849836355f9..606869d0c982 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1944,7 +1944,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
 		intel_dsi->dsi_hosts[port] = host;
 	}
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, NULL);
 
 	if (!intel_dsi_vbt_init(intel_dsi, MIPI_DSI_GENERIC_PANEL_ID)) {
 		drm_dbg_kms(&dev_priv->drm, "no device found\n");
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 19/22] drm/i915/bios: Parse the seamless DRRS min refresh rate
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (17 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 18/22] drm/i915/bios: Determine panel type via PNPID match Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-07 17:56   ` Jani Nikula
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 20/22] drm/i915: Respect VBT " Ville Syrjala
                   ` (13 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Extract the seamless DRRS min refresh rate from the VBT.

v2: Do a version check

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 9 ++++++++-
 drivers/gpu/drm/i915/i915_drv.h           | 1 +
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index cfdfe91d4ccf..d561551d6324 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -802,6 +802,7 @@ parse_lfp_data(struct drm_i915_private *i915)
 	const struct bdb_lvds_lfp_data *data;
 	const struct bdb_lvds_lfp_data_tail *tail;
 	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+	int panel_type = i915->vbt.panel_type;
 
 	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
 	if (!ptrs)
@@ -818,7 +819,13 @@ parse_lfp_data(struct drm_i915_private *i915)
 	if (!tail)
 		return;
 
-	(void)tail;
+	if (i915->vbt.version >= 188) {
+		i915->vbt.seamless_drrs_min_refresh_rate =
+			tail->seamless_drrs_min_refresh_rate[panel_type];
+		drm_dbg_kms(&i915->drm,
+			    "Seamless DRRS min refresh rate: %d Hz\n",
+			    i915->vbt.seamless_drrs_min_refresh_rate);
+	}
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9274417cd87a..7b6858651420 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -327,6 +327,7 @@ struct intel_vbt_data {
 	bool override_afc_startup;
 	u8 override_afc_startup_val;
 
+	u8 seamless_drrs_min_refresh_rate;
 	enum drrs_type drrs_type;
 
 	struct {
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 20/22] drm/i915: Respect VBT seamless DRRS min refresh rate
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (18 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 19/22] drm/i915/bios: Parse the seamless DRRS min refresh rate Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-07 18:01   ` Jani Nikula
  2022-04-05 17:34   ` [Intel-gfx] " Ville Syrjala
                   ` (12 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make sure our choice of downclock mode respects the VBT
seameless DRRS min refresh rate limit.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_panel.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 03398feb6676..35d8676438a3 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -75,13 +75,17 @@ const struct drm_display_mode *
 intel_panel_downclock_mode(struct intel_connector *connector,
 			   const struct drm_display_mode *adjusted_mode)
 {
+	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 	const struct drm_display_mode *fixed_mode, *best_mode = NULL;
-	int vrefresh = drm_mode_vrefresh(adjusted_mode);
+	int min_vrefresh = i915->vbt.seamless_drrs_min_refresh_rate;
+	int max_vrefresh = drm_mode_vrefresh(adjusted_mode);
 
 	/* pick the fixed_mode with the lowest refresh rate */
 	list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
-		if (drm_mode_vrefresh(fixed_mode) < vrefresh) {
-			vrefresh = drm_mode_vrefresh(fixed_mode);
+		int vrefesh = drm_mode_vrefresh(fixed_mode);
+
+		if (vrefesh >= min_vrefresh && vrefesh < max_vrefresh) {
+			max_vrefresh = vrefesh;
 			best_mode = fixed_mode;
 		}
 	}
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 21/22] drm/edid: Extract drm_edid_decode_mfg_id()
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
@ 2022-04-05 17:34   ` Ville Syrjala
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 02/22] drm/i915/bios: Make copies of VBT data blocks Ville Syrjala
                     ` (31 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make the PNPID decoding available for other users.

Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_edid.h | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index b7e170584000..5e9d7fcda8e7 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -508,6 +508,22 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
 	return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK;
 }
 
+/**
+ * drm_edid_decode_mfg_id - Decode the manufacturer ID
+ * @mfg_id: The manufacturer ID
+ * @vend: A 4-byte buffer to store the 3-letter vendor string plus a '\0'
+ *	  termination
+ */
+static inline const char *drm_edid_decode_mfg_id(u16 mfg_id, char vend[4])
+{
+	vend[0] = '@' + ((mfg_id >> 10) & 0x1f);
+	vend[1] = '@' + ((mfg_id >> 5) & 0x1f);
+	vend[2] = '@' + ((mfg_id >> 0) & 0x1f);
+	vend[3] = '\0';
+
+	return vend;
+}
+
 /**
  * drm_edid_encode_panel_id - Encode an ID for matching against drm_edid_get_panel_id()
  * @vend_chr_0: First character of the vendor string.
@@ -548,10 +564,7 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
 static inline void drm_edid_decode_panel_id(u32 panel_id, char vend[4], u16 *product_id)
 {
 	*product_id = (u16)(panel_id & 0xffff);
-	vend[0] = '@' + ((panel_id >> 26) & 0x1f);
-	vend[1] = '@' + ((panel_id >> 21) & 0x1f);
-	vend[2] = '@' + ((panel_id >> 16) & 0x1f);
-	vend[3] = '\0';
+	drm_edid_decode_mfg_id(panel_id >> 16, vend);
 }
 
 bool drm_probe_ddc(struct i2c_adapter *adapter);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 21/22] drm/edid: Extract drm_edid_decode_mfg_id()
@ 2022-04-05 17:34   ` Ville Syrjala
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx; +Cc: dri-devel

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make the PNPID decoding available for other users.

Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 include/drm/drm_edid.h | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index b7e170584000..5e9d7fcda8e7 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -508,6 +508,22 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
 	return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK;
 }
 
+/**
+ * drm_edid_decode_mfg_id - Decode the manufacturer ID
+ * @mfg_id: The manufacturer ID
+ * @vend: A 4-byte buffer to store the 3-letter vendor string plus a '\0'
+ *	  termination
+ */
+static inline const char *drm_edid_decode_mfg_id(u16 mfg_id, char vend[4])
+{
+	vend[0] = '@' + ((mfg_id >> 10) & 0x1f);
+	vend[1] = '@' + ((mfg_id >> 5) & 0x1f);
+	vend[2] = '@' + ((mfg_id >> 0) & 0x1f);
+	vend[3] = '\0';
+
+	return vend;
+}
+
 /**
  * drm_edid_encode_panel_id - Encode an ID for matching against drm_edid_get_panel_id()
  * @vend_chr_0: First character of the vendor string.
@@ -548,10 +564,7 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
 static inline void drm_edid_decode_panel_id(u32 panel_id, char vend[4], u16 *product_id)
 {
 	*product_id = (u16)(panel_id & 0xffff);
-	vend[0] = '@' + ((panel_id >> 26) & 0x1f);
-	vend[1] = '@' + ((panel_id >> 21) & 0x1f);
-	vend[2] = '@' + ((panel_id >> 16) & 0x1f);
-	vend[3] = '\0';
+	drm_edid_decode_mfg_id(panel_id >> 16, vend);
 }
 
 bool drm_probe_ddc(struct i2c_adapter *adapter);
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v2 22/22] drm/i915/bios: Dump PNPID and panel name
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (20 preceding siblings ...)
  2022-04-05 17:34   ` [Intel-gfx] " Ville Syrjala
@ 2022-04-05 17:34 ` Ville Syrjala
  2022-04-07 18:07   ` Jani Nikula
  2022-04-05 22:55 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Patchwork
                   ` (10 subsequent siblings)
  32 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-05 17:34 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Dump the panel PNPID and name from the VBT.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 24 +++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index d561551d6324..953526a7dc5d 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -25,6 +25,7 @@
  *
  */
 
+#include <drm/drm_edid.h>
 #include <drm/dp/drm_dp_helper.h>
 
 #include "display/intel_display.h"
@@ -597,6 +598,19 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
 		return NULL;
 }
 
+static void dump_pnp_id(struct drm_i915_private *i915,
+			const struct lvds_pnp_id *pnp_id,
+			const char *name)
+{
+	u16 mfg_name = be16_to_cpu((__force __be16)pnp_id->mfg_name);
+	char vend[4];
+
+	drm_dbg_kms(&i915->drm, "%s PNPID mfg: %s (0x%x), prod: %u, serial: %u, week: %d, year: %d\n",
+		    name, drm_edid_decode_mfg_id(mfg_name, vend),
+		    pnp_id->mfg_name, pnp_id->product_code, pnp_id->serial,
+		    pnp_id->mfg_week, pnp_id->mfg_year + 1990);
+}
+
 static int pnp_id_panel_type(struct drm_i915_private *i915,
 			     const struct edid *edid)
 {
@@ -615,6 +629,8 @@ static int pnp_id_panel_type(struct drm_i915_private *i915,
 	edid_id_nodate.mfg_week = 0;
 	edid_id_nodate.mfg_year = 0;
 
+	dump_pnp_id(i915, edid_id, "EDID");
+
 	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
 	if (!ptrs)
 		return -1;
@@ -802,6 +818,7 @@ parse_lfp_data(struct drm_i915_private *i915)
 	const struct bdb_lvds_lfp_data *data;
 	const struct bdb_lvds_lfp_data_tail *tail;
 	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+	const struct lvds_pnp_id *pnp_id;
 	int panel_type = i915->vbt.panel_type;
 
 	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
@@ -815,10 +832,17 @@ parse_lfp_data(struct drm_i915_private *i915)
 	if (!i915->vbt.lfp_lvds_vbt_mode)
 		parse_lfp_panel_dtd(i915, data, ptrs);
 
+	pnp_id = get_lvds_pnp_id(data, ptrs, panel_type);
+	dump_pnp_id(i915, pnp_id, "Panel");
+
 	tail = get_lfp_data_tail(data, ptrs);
 	if (!tail)
 		return;
 
+	drm_dbg_kms(&i915->drm, "Panel name: %.*s\n",
+		    (int)sizeof(tail->panel_name[0].name),
+		    tail->panel_name[panel_type].name);
+
 	if (i915->vbt.version >= 188) {
 		i915->vbt.seamless_drrs_min_refresh_rate =
 			tail->seamless_drrs_min_refresh_rate[panel_type];
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (21 preceding siblings ...)
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 22/22] drm/i915/bios: Dump PNPID and panel name Ville Syrjala
@ 2022-04-05 22:55 ` Patchwork
  2022-04-05 22:57 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-05 22:55 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
05d9638c2980 drm/i915/bios: Use the cached BDB version
578166bc3056 drm/i915/bios: Make copies of VBT data blocks
90add1560515 drm/i915/bios: Use the copy of the LFP data table always
cccb9f6e5310 drm/i915/bios: Validate LFP data table pointers
-:93: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#93: FILE: drivers/gpu/drm/i915/display/intel_bios.c:257:
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||

-:93: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#93: FILE: drivers/gpu/drm/i915/display/intel_bios.c:257:
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
 		                                               ^

-:94: WARNING:LONG_LINE: line length of 105 exceeds 100 columns
#94: FILE: drivers/gpu/drm/i915/display/intel_bios.c:258:
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||

-:94: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#94: FILE: drivers/gpu/drm/i915/display/intel_bios.c:258:
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
 		                                                ^

-:95: WARNING:LONG_LINE: line length of 107 exceeds 100 columns
#95: FILE: drivers/gpu/drm/i915/display/intel_bios.c:259:
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)

-:95: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#95: FILE: drivers/gpu/drm/i915/display/intel_bios.c:259:
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
 		                                                  ^

total: 0 errors, 3 warnings, 3 checks, 100 lines checked
73c2bd353d63 drm/i915/bios: Trust the LFP data pointers
0ca5de1a6532 drm/i915/bios: Validate the panel_name table
057a8b805d81 drm/i915/bios: Reorder panel DTD parsing
086e15f0d645 drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
-:44: CHECK:SPACING: spaces preferred around that '+' (ctx:VxV)
#44: FILE: drivers/gpu/drm/i915/display/intel_bios.c:321:
+		if (data[i] == 0xff && data[i+1] == 0xff)
 		                             ^

-:128: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#128: FILE: drivers/gpu/drm/i915/display/intel_bios.c:405:
+		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
 		                                                       ^

-:129: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#129: FILE: drivers/gpu/drm/i915/display/intel_bios.c:406:
+		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
 		                                                        ^

-:130: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#130: FILE: drivers/gpu/drm/i915/display/intel_bios.c:407:
+		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
 		                                                          ^

total: 0 errors, 0 warnings, 4 checks, 160 lines checked
d07d7dcf7c2d drm/i915/bios: Get access to the tail end of the LFP data block
f00aa539537f drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
e1742d2d9cf5 drm/i915/bios: Split parse_driver_features() into two parts
36484fb6dd23 drm/i915/bios: Split VBT parsing to global vs. panel specific parts
d1fd524d3ca5 drm/i915/pps: Split PPS init+sanitize in two
258da58b3f75 drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
90cb9845428d drm/i915/bios: Do panel specific VBT parsing later
2c6005cc3af9 drm/i915/bios: Extract get_panel_type()
53decd0e521a drm/i915/bios: Refactor panel_type code
179efa1ac625 drm/i915/bios: Determine panel type via PNPID match
00d122192a92 drm/i915/bios: Parse the seamless DRRS min refresh rate
2d62931bb39e drm/i915: Respect VBT seamless DRRS min refresh rate
39a5b7b20e53 drm/edid: Extract drm_edid_decode_mfg_id()
e1e2c24beed6 drm/i915/bios: Dump PNPID and panel name



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (22 preceding siblings ...)
  2022-04-05 22:55 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Patchwork
@ 2022-04-05 22:57 ` Patchwork
  2022-04-05 23:02 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-05 22:57 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.DOCS: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (23 preceding siblings ...)
  2022-04-05 22:57 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2022-04-05 23:02 ` Patchwork
  2022-04-05 23:27 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-05 23:02 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ make htmldocs 2>&1 > /dev/null | grep i915
./drivers/gpu/drm/i915/gem/i915_gem_context_types.h:417: warning: Function parameter or member 'client_link' not described in 'i915_gem_context'



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.BAT: failure for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (24 preceding siblings ...)
  2022-04-05 23:02 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
@ 2022-04-05 23:27 ` Patchwork
  2022-04-06 18:17 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4) Patchwork
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-05 23:27 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 6118 bytes --]

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching
URL   : https://patchwork.freedesktop.org/series/102213/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_11458 -> Patchwork_22788
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_22788 absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_22788, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/index.html

Participating hosts (37 -> 34)
------------------------------

  Missing    (3): fi-kbl-soraka fi-bsw-cyan fi-bdw-samus 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22788:

### IGT changes ###

#### Possible regressions ####

  * igt@runner@aborted:
    - fi-rkl-11600:       NOTRUN -> [FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-rkl-11600/igt@runner@aborted.html
    - fi-bwr-2160:        NOTRUN -> [FAIL][2]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-bwr-2160/igt@runner@aborted.html
    - fi-rkl-guc:         NOTRUN -> [FAIL][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-rkl-guc/igt@runner@aborted.html
    - fi-bxt-dsi:         NOTRUN -> [FAIL][4]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-bxt-dsi/igt@runner@aborted.html
    - fi-adl-ddr5:        NOTRUN -> [FAIL][5]
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-adl-ddr5/igt@runner@aborted.html
    - fi-elk-e7500:       NOTRUN -> [FAIL][6]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-elk-e7500/igt@runner@aborted.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@runner@aborted:
    - {fi-jsl-1}:         NOTRUN -> [FAIL][7]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-jsl-1/igt@runner@aborted.html
    - {fi-ehl-2}:         NOTRUN -> [FAIL][8]
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-ehl-2/igt@runner@aborted.html

  
Known issues
------------

  Here are the changes found in Patchwork_22788 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        [PASS][9] -> [INCOMPLETE][10] ([i915#4785])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11458/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html

  * igt@runner@aborted:
    - fi-hsw-4770:        NOTRUN -> [FAIL][11] ([fdo#109271] / [i915#2722] / [i915#4312])
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-hsw-4770/igt@runner@aborted.html
    - fi-tgl-1115g4:      NOTRUN -> [FAIL][12] ([i915#3690])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-tgl-1115g4/igt@runner@aborted.html
    - fi-tgl-u2:          NOTRUN -> [FAIL][13] ([i915#3690])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-tgl-u2/igt@runner@aborted.html
    - fi-blb-e6850:       NOTRUN -> [FAIL][14] ([i915#2403])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/fi-blb-e6850/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [i915#2403]: https://gitlab.freedesktop.org/drm/intel/issues/2403
  [i915#2722]: https://gitlab.freedesktop.org/drm/intel/issues/2722
  [i915#3690]: https://gitlab.freedesktop.org/drm/intel/issues/3690
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4785]: https://gitlab.freedesktop.org/drm/intel/issues/4785


Build changes
-------------

  * Linux: CI_DRM_11458 -> Patchwork_22788

  CI-20190529: 20190529
  CI_DRM_11458: 7b4967c734a7c99ff69154d062a071181021e49d @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6410: cc359d5d2d3fc8be50340ba0379bacaf5c37bc5f @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22788: e1e2c24beed668c078fd7851a4e3ec8ee87329d8 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

e1e2c24beed6 drm/i915/bios: Dump PNPID and panel name
39a5b7b20e53 drm/edid: Extract drm_edid_decode_mfg_id()
2d62931bb39e drm/i915: Respect VBT seamless DRRS min refresh rate
00d122192a92 drm/i915/bios: Parse the seamless DRRS min refresh rate
179efa1ac625 drm/i915/bios: Determine panel type via PNPID match
53decd0e521a drm/i915/bios: Refactor panel_type code
2c6005cc3af9 drm/i915/bios: Extract get_panel_type()
90cb9845428d drm/i915/bios: Do panel specific VBT parsing later
258da58b3f75 drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
d1fd524d3ca5 drm/i915/pps: Split PPS init+sanitize in two
36484fb6dd23 drm/i915/bios: Split VBT parsing to global vs. panel specific parts
e1742d2d9cf5 drm/i915/bios: Split parse_driver_features() into two parts
f00aa539537f drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
d07d7dcf7c2d drm/i915/bios: Get access to the tail end of the LFP data block
086e15f0d645 drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
057a8b805d81 drm/i915/bios: Reorder panel DTD parsing
0ca5de1a6532 drm/i915/bios: Validate the panel_name table
73c2bd353d63 drm/i915/bios: Trust the LFP data pointers
cccb9f6e5310 drm/i915/bios: Validate LFP data table pointers
90add1560515 drm/i915/bios: Use the copy of the LFP data table always
578166bc3056 drm/i915/bios: Make copies of VBT data blocks
05d9638c2980 drm/i915/bios: Use the cached BDB version

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22788/index.html

[-- Attachment #2: Type: text/html, Size: 7197 bytes --]

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v3 02/22] drm/i915/bios: Make copies of VBT data blocks
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 02/22] drm/i915/bios: Make copies of VBT data blocks Ville Syrjala
@ 2022-04-06 13:38   ` Ville Syrjala
  2022-04-07 10:23     ` Jani Nikula
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-06 13:38 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make a copy of each VB data block with a guaranteed minimum
size. The extra (if any) will just be left zeroed.

This means we don't have to worry about going out of bounds
when accessing any of the structure members. Otherwise that
could easliy happen if we simply get the version check wrong,
or if the VBT is broken/malicious.

v2: Don't do arithmetic between bdb header and copy
    of the LFP data block (Jani)
v3: Make all the copies up front
v4: Only WARN about min_size==0 if we found the block

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 230 ++++++++++++++++------
 drivers/gpu/drm/i915/i915_drv.h           |   1 +
 2 files changed, 174 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 5518f4cfa1b1..068978734e3b 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
 }
 
 static const void *
-find_section(const void *_bdb, enum bdb_block_id section_id)
+find_raw_section(const void *_bdb, enum bdb_block_id section_id)
 {
 	const struct bdb_header *bdb = _bdb;
 	const u8 *base = _bdb;
@@ -118,6 +118,124 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
 	return NULL;
 }
 
+/*
+ * Offset from the start of BDB to the start of the
+ * block data (just past the block header).
+ */
+static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
+{
+	const void *block;
+
+	block = find_raw_section(bdb, section_id);
+	if (!block)
+		return 0;
+
+	return block - bdb;
+}
+
+struct bdb_block_entry {
+	struct list_head node;
+	enum bdb_block_id section_id;
+	u8 data[];
+};
+
+static const void *
+find_section(struct drm_i915_private *i915,
+	     enum bdb_block_id section_id)
+{
+	struct bdb_block_entry *entry;
+
+	list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
+		if (entry->section_id == section_id)
+			return entry->data + 3;
+	}
+
+	return NULL;
+}
+
+static const struct {
+	enum bdb_block_id section_id;
+	size_t min_size;
+} bdb_blocks[] = {
+	{ .section_id = BDB_GENERAL_FEATURES,
+	  .min_size = sizeof(struct bdb_general_features), },
+	{ .section_id = BDB_GENERAL_DEFINITIONS,
+	  .min_size = sizeof(struct bdb_general_definitions), },
+	{ .section_id = BDB_PSR,
+	  .min_size = sizeof(struct bdb_psr), },
+	{ .section_id = BDB_DRIVER_FEATURES,
+	  .min_size = sizeof(struct bdb_driver_features), },
+	{ .section_id = BDB_SDVO_LVDS_OPTIONS,
+	  .min_size = sizeof(struct bdb_sdvo_lvds_options), },
+	{ .section_id = BDB_SDVO_PANEL_DTDS,
+	  .min_size = sizeof(struct bdb_sdvo_panel_dtds), },
+	{ .section_id = BDB_EDP,
+	  .min_size = sizeof(struct bdb_edp), },
+	{ .section_id = BDB_LVDS_OPTIONS,
+	  .min_size = sizeof(struct bdb_lvds_options), },
+	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
+	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
+	{ .section_id = BDB_LVDS_LFP_DATA,
+	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
+	{ .section_id = BDB_LVDS_BACKLIGHT,
+	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
+	{ .section_id = BDB_LFP_POWER,
+	  .min_size = sizeof(struct bdb_lfp_power), },
+	{ .section_id = BDB_MIPI_CONFIG,
+	  .min_size = sizeof(struct bdb_mipi_config), },
+	{ .section_id = BDB_MIPI_SEQUENCE,
+	  .min_size = sizeof(struct bdb_mipi_sequence) },
+	{ .section_id = BDB_COMPRESSION_PARAMETERS,
+	  .min_size = sizeof(struct bdb_compression_parameters), },
+	{ .section_id = BDB_GENERIC_DTD,
+	  .min_size = sizeof(struct bdb_generic_dtd), },
+};
+
+static void
+init_bdb_block(struct drm_i915_private *i915,
+	       const void *bdb, enum bdb_block_id section_id,
+	       size_t min_size)
+{
+	struct bdb_block_entry *entry;
+	const void *block;
+	size_t block_size;
+
+	block = find_raw_section(bdb, section_id);
+	if (!block)
+		return;
+
+	drm_WARN(&i915->drm, min_size == 0,
+		 "Block %d min_size is zero\n", section_id);
+
+	block_size = get_blocksize(block);
+
+	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
+			GFP_KERNEL);
+	if (!entry)
+		return;
+
+	entry->section_id = section_id;
+	memcpy(entry->data, block - 3, block_size + 3);
+
+	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
+		    section_id, block_size, min_size);
+
+	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
+}
+
+static void init_bdb_blocks(struct drm_i915_private *i915,
+			    const void *bdb)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
+		enum bdb_block_id section_id = bdb_blocks[i].section_id;
+		size_t min_size = bdb_blocks[i].min_size;
+
+		init_bdb_block(i915, bdb, section_id, min_size);
+	}
+}
+
 static void
 fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
 			const struct lvds_dvo_timing *dvo_timing)
@@ -199,7 +317,7 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
 		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
 		   int index)
 {
-	size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
+	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
 	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
 	size_t ofs;
 
@@ -214,15 +332,14 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
 
 /* Parse general panel options */
 static void
-parse_panel_options(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_panel_options(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_options *lvds_options;
 	int panel_type;
 	int drrs_mode;
 	int ret;
 
-	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
 		return;
 
@@ -285,11 +402,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
 	struct drm_display_mode *panel_fixed_mode;
 	int panel_type = i915->vbt.panel_type;
 
-	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
 	if (!lvds_lfp_data)
 		return;
 
-	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
 	if (!lvds_lfp_data_ptrs)
 		return;
 
@@ -325,15 +442,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
 }
 
 static void
-parse_generic_dtd(struct drm_i915_private *i915,
-		  const struct bdb_header *bdb)
+parse_generic_dtd(struct drm_i915_private *i915)
 {
 	const struct bdb_generic_dtd *generic_dtd;
 	const struct generic_dtd_entry *dtd;
 	struct drm_display_mode *panel_fixed_mode;
 	int num_dtd;
 
-	generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
+	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
 	if (!generic_dtd)
 		return;
 
@@ -416,21 +532,20 @@ parse_panel_dtd(struct drm_i915_private *i915,
 	 * back to trying the old LFP block if that fails.
 	 */
 	if (i915->vbt.version >= 229)
-		parse_generic_dtd(i915, bdb);
+		parse_generic_dtd(i915);
 	if (!i915->vbt.lfp_lvds_vbt_mode)
 		parse_lfp_panel_dtd(i915, bdb);
 }
 
 static void
-parse_lfp_backlight(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_lfp_backlight(struct drm_i915_private *i915)
 {
 	const struct bdb_lfp_backlight_data *backlight_data;
 	const struct lfp_backlight_data_entry *entry;
 	int panel_type = i915->vbt.panel_type;
 	u16 level;
 
-	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
+	backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
 	if (!backlight_data)
 		return;
 
@@ -514,8 +629,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
 
 /* Try to find sdvo panel data */
 static void
-parse_sdvo_panel_data(struct drm_i915_private *i915,
-		      const struct bdb_header *bdb)
+parse_sdvo_panel_data(struct drm_i915_private *i915)
 {
 	const struct bdb_sdvo_panel_dtds *dtds;
 	struct drm_display_mode *panel_fixed_mode;
@@ -531,14 +645,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
 	if (index == -1) {
 		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 
-		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+		sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
 		if (!sdvo_lvds_options)
 			return;
 
 		index = sdvo_lvds_options->panel_type;
 	}
 
-	dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+	dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
 	if (!dtds)
 		return;
 
@@ -570,12 +684,11 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
 }
 
 static void
-parse_general_features(struct drm_i915_private *i915,
-		       const struct bdb_header *bdb)
+parse_general_features(struct drm_i915_private *i915)
 {
 	const struct bdb_general_features *general;
 
-	general = find_section(bdb, BDB_GENERAL_FEATURES);
+	general = find_section(i915, BDB_GENERAL_FEATURES);
 	if (!general)
 		return;
 
@@ -695,12 +808,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
 }
 
 static void
-parse_driver_features(struct drm_i915_private *i915,
-		      const struct bdb_header *bdb)
+parse_driver_features(struct drm_i915_private *i915)
 {
 	const struct bdb_driver_features *driver;
 
-	driver = find_section(bdb, BDB_DRIVER_FEATURES);
+	driver = find_section(i915, BDB_DRIVER_FEATURES);
 	if (!driver)
 		return;
 
@@ -747,8 +859,7 @@ parse_driver_features(struct drm_i915_private *i915,
 }
 
 static void
-parse_power_conservation_features(struct drm_i915_private *i915,
-				  const struct bdb_header *bdb)
+parse_power_conservation_features(struct drm_i915_private *i915)
 {
 	const struct bdb_lfp_power *power;
 	u8 panel_type = i915->vbt.panel_type;
@@ -756,7 +867,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
 	if (i915->vbt.version < 228)
 		return;
 
-	power = find_section(bdb, BDB_LFP_POWER);
+	power = find_section(i915, BDB_LFP_POWER);
 	if (!power)
 		return;
 
@@ -776,14 +887,14 @@ parse_power_conservation_features(struct drm_i915_private *i915,
 }
 
 static void
-parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
+parse_edp(struct drm_i915_private *i915)
 {
 	const struct bdb_edp *edp;
 	const struct edp_power_seq *edp_pps;
 	const struct edp_fast_link_params *edp_link_params;
 	int panel_type = i915->vbt.panel_type;
 
-	edp = find_section(bdb, BDB_EDP);
+	edp = find_section(i915, BDB_EDP);
 	if (!edp)
 		return;
 
@@ -894,13 +1005,13 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
 }
 
 static void
-parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
+parse_psr(struct drm_i915_private *i915)
 {
 	const struct bdb_psr *psr;
 	const struct psr_table *psr_table;
 	int panel_type = i915->vbt.panel_type;
 
-	psr = find_section(bdb, BDB_PSR);
+	psr = find_section(i915, BDB_PSR);
 	if (!psr) {
 		drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
 		return;
@@ -1034,8 +1145,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
 }
 
 static void
-parse_mipi_config(struct drm_i915_private *i915,
-		  const struct bdb_header *bdb)
+parse_mipi_config(struct drm_i915_private *i915)
 {
 	const struct bdb_mipi_config *start;
 	const struct mipi_config *config;
@@ -1058,7 +1168,7 @@ parse_mipi_config(struct drm_i915_private *i915,
 	/* Parse #52 for panel index used from panel_type already
 	 * parsed
 	 */
-	start = find_section(bdb, BDB_MIPI_CONFIG);
+	start = find_section(i915, BDB_MIPI_CONFIG);
 	if (!start) {
 		drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
 		return;
@@ -1354,8 +1464,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
 }
 
 static void
-parse_mipi_sequence(struct drm_i915_private *i915,
-		    const struct bdb_header *bdb)
+parse_mipi_sequence(struct drm_i915_private *i915)
 {
 	int panel_type = i915->vbt.panel_type;
 	const struct bdb_mipi_sequence *sequence;
@@ -1368,7 +1477,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
 	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
 		return;
 
-	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
+	sequence = find_section(i915, BDB_MIPI_SEQUENCE);
 	if (!sequence) {
 		drm_dbg_kms(&i915->drm,
 			    "No MIPI Sequence found, parsing complete\n");
@@ -1439,8 +1548,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
 }
 
 static void
-parse_compression_parameters(struct drm_i915_private *i915,
-			     const struct bdb_header *bdb)
+parse_compression_parameters(struct drm_i915_private *i915)
 {
 	const struct bdb_compression_parameters *params;
 	struct intel_bios_encoder_data *devdata;
@@ -1451,7 +1559,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
 	if (i915->vbt.version < 198)
 		return;
 
-	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
+	params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
 	if (params) {
 		/* Sanity checks */
 		if (params->entry_size != sizeof(params->data[0])) {
@@ -2086,8 +2194,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
 }
 
 static void
-parse_general_definitions(struct drm_i915_private *i915,
-			  const struct bdb_header *bdb)
+parse_general_definitions(struct drm_i915_private *i915)
 {
 	const struct bdb_general_definitions *defs;
 	struct intel_bios_encoder_data *devdata;
@@ -2097,7 +2204,7 @@ parse_general_definitions(struct drm_i915_private *i915,
 	u16 block_size;
 	int bus_pin;
 
-	defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
 	if (!defs) {
 		drm_dbg_kms(&i915->drm,
 			    "No general definition block is found, no devices defined.\n");
@@ -2466,6 +2573,7 @@ void intel_bios_init(struct drm_i915_private *i915)
 	const struct bdb_header *bdb;
 
 	INIT_LIST_HEAD(&i915->vbt.display_devices);
+	INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
 
 	if (!HAS_DISPLAY(i915)) {
 		drm_dbg_kms(&i915->drm,
@@ -2499,22 +2607,24 @@ void intel_bios_init(struct drm_i915_private *i915)
 		    "VBT signature \"%.*s\", BDB version %d\n",
 		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
 
+	init_bdb_blocks(i915, bdb);
+
 	/* Grab useful general definitions */
-	parse_general_features(i915, bdb);
-	parse_general_definitions(i915, bdb);
-	parse_panel_options(i915, bdb);
+	parse_general_features(i915);
+	parse_general_definitions(i915);
+	parse_panel_options(i915);
 	parse_panel_dtd(i915, bdb);
-	parse_lfp_backlight(i915, bdb);
-	parse_sdvo_panel_data(i915, bdb);
-	parse_driver_features(i915, bdb);
-	parse_power_conservation_features(i915, bdb);
-	parse_edp(i915, bdb);
-	parse_psr(i915, bdb);
-	parse_mipi_config(i915, bdb);
-	parse_mipi_sequence(i915, bdb);
+	parse_lfp_backlight(i915);
+	parse_sdvo_panel_data(i915);
+	parse_driver_features(i915);
+	parse_power_conservation_features(i915);
+	parse_edp(i915);
+	parse_psr(i915);
+	parse_mipi_config(i915);
+	parse_mipi_sequence(i915);
 
 	/* Depends on child device list */
-	parse_compression_parameters(i915, bdb);
+	parse_compression_parameters(i915);
 
 out:
 	if (!vbt) {
@@ -2536,14 +2646,20 @@ void intel_bios_init(struct drm_i915_private *i915)
  */
 void intel_bios_driver_remove(struct drm_i915_private *i915)
 {
-	struct intel_bios_encoder_data *devdata, *n;
+	struct intel_bios_encoder_data *devdata, *nd;
+	struct bdb_block_entry *entry, *ne;
 
-	list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
+	list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
 		list_del(&devdata->node);
 		kfree(devdata->dsc);
 		kfree(devdata);
 	}
 
+	list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
+		list_del(&entry->node);
+		kfree(entry);
+	}
+
 	kfree(i915->vbt.sdvo_lvds_vbt_mode);
 	i915->vbt.sdvo_lvds_vbt_mode = NULL;
 	kfree(i915->vbt.lfp_lvds_vbt_mode);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 06e7c2802c5e..9274417cd87a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -380,6 +380,7 @@ struct intel_vbt_data {
 	int crt_ddc_pin;
 
 	struct list_head display_devices;
+	struct list_head bdb_blocks;
 
 	struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
 	struct sdvo_device_mapping sdvo_mappings[2];
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v3 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them Ville Syrjala
@ 2022-04-06 13:39   ` Ville Syrjala
  2022-04-07 12:24     ` Jani Nikula
  2022-04-07 16:53     ` Jani Nikula
  0 siblings, 2 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-06 13:39 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Modern VBTs no longer contain the LFP data table pointers
block (41). We are expecting to have one in order to be able
to parse the LFP data block (42), so let's make one up.

Since the fp_timing table has variable size we must somehow
determine its size. Rather than just hardcode it we look for
the terminator bytes (0xffff) to figure out where each table
entry starts. dvo_timing, panel_pnp_id, and panel_name are
expected to have fixed size.

This has been observed on various machines, eg. TGL with BDB
version 240, CML with BDB version 231, etc. The most recent
VBT I've observed that still had block 41 had BDB version
228. So presumably the cutoff (if an exact cutoff even exists)
is somewhere around BDB version 229-231.

v2: kfree the thing we allocated, not the thing+3 bytes
v3: Do the debugprint only if we found the LFP data block

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c | 136 +++++++++++++++++++++-
 1 file changed, 135 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 8b118c54314d..d32091dad1b0 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -310,16 +310,146 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
 	return validate_lfp_data_ptrs(bdb, ptrs);
 }
 
+static const void *find_fp_timing_terminator(const u8 *data, int size)
+{
+	int i;
+
+	if (!data)
+		return NULL;
+
+	for (i = 0; i < size - 1; i++) {
+		if (data[i] == 0xff && data[i+1] == 0xff)
+			return &data[i];
+	}
+
+	return NULL;
+}
+
+static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
+			     int table_size, int total_size)
+{
+	if (total_size < table_size)
+		return total_size;
+
+	table->table_size = table_size;
+	table->offset = total_size - table_size;
+
+	return total_size - table_size;
+}
+
+static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
+			      const struct lvds_lfp_data_ptr_table *prev,
+			      int size)
+{
+	next->table_size = prev->table_size;
+	next->offset = prev->offset + size;
+}
+
+static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
+				    const void *bdb)
+{
+	int i, size, table_size, block_size, offset;
+	const void *t0, *t1, *block;
+	struct bdb_lvds_lfp_data_ptrs *ptrs;
+	void *ptrs_block;
+
+	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
+	if (!block)
+		return NULL;
+
+	drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
+
+	block_size = get_blocksize(block);
+
+	size = block_size;
+	t0 = find_fp_timing_terminator(block, size);
+
+	size -= t0 - block - 2;
+	t1 = find_fp_timing_terminator(t0 + 2, size);
+
+	if (!t0 || !t1)
+		return NULL;
+
+	size = t1 - t0;
+	if (size * 16 > block_size)
+		return NULL;
+
+	ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
+	if (!ptrs_block)
+		return NULL;
+
+	*(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS;
+	*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
+	ptrs = ptrs_block + 3;
+
+	table_size = sizeof(struct lvds_pnp_id);
+	size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
+
+	table_size = sizeof(struct lvds_dvo_timing);
+	size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
+
+	table_size = t0 - block + 2;
+	size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
+
+	if (ptrs->ptr[0].fp_timing.table_size)
+		ptrs->lvds_entries++;
+	if (ptrs->ptr[0].dvo_timing.table_size)
+		ptrs->lvds_entries++;
+	if (ptrs->ptr[0].panel_pnp_id.table_size)
+		ptrs->lvds_entries++;
+
+	if (size != 0 || ptrs->lvds_entries != 3) {
+		kfree(ptrs);
+		return NULL;
+	}
+
+	size = t1 - t0;
+	for (i = 1; i < 16; i++) {
+		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
+		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
+		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
+	}
+
+	size = t1 - t0;
+	table_size = sizeof(struct lvds_lfp_panel_name);
+
+	if (16 * (size + table_size) <= block_size) {
+		ptrs->panel_name.table_size = table_size;
+		ptrs->panel_name.offset = size * 16;
+	}
+
+	offset = block - bdb;
+
+	for (i = 0; i < 16; i++) {
+		ptrs->ptr[i].fp_timing.offset += offset;
+		ptrs->ptr[i].dvo_timing.offset += offset;
+		ptrs->ptr[i].panel_pnp_id.offset += offset;
+	}
+
+	if (ptrs->panel_name.table_size)
+		ptrs->panel_name.offset += offset;
+
+	return ptrs_block;
+}
+
 static void
 init_bdb_block(struct drm_i915_private *i915,
 	       const void *bdb, enum bdb_block_id section_id,
 	       size_t min_size)
 {
 	struct bdb_block_entry *entry;
+	void *temp_block = NULL;
 	const void *block;
 	size_t block_size;
 
 	block = find_raw_section(bdb, section_id);
+
+	/* Modern VBTs lack the LFP data table pointers block, make one up */
+	if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) {
+		temp_block = generate_lfp_data_ptrs(i915, bdb);
+		if (temp_block)
+			block = temp_block + 3;
+	}
 	if (!block)
 		return;
 
@@ -330,12 +460,16 @@ init_bdb_block(struct drm_i915_private *i915,
 
 	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
 			GFP_KERNEL);
-	if (!entry)
+	if (!entry) {
+		kfree(temp_block);
 		return;
+	}
 
 	entry->section_id = section_id;
 	memcpy(entry->data, block - 3, block_size + 3);
 
+	kfree(temp_block);
+
 	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
 		    section_id, block_size, min_size);
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v3 09/22] drm/i915/bios: Get access to the tail end of the LFP data block
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 09/22] drm/i915/bios: Get access to the tail end of the LFP data block Ville Syrjala
@ 2022-04-06 13:40   ` Ville Syrjala
  2022-04-07 17:07     ` Jani Nikula
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-06 13:40 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

We need to start parsing stuff from the tail end of the LFP data block.
This is made awkward by the fact that the fp_timing table has variable
size. So we must use a bit more finesse to get the tail end, and to
make sure we allocate enough memory for it to make sure our struct
representation fits.

v2: Rebase due to the preallocation of BDB blocks
v3: Rebase due to min_size WARN relocation

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/intel_bios.c     | 39 ++++++++++++++++++-
 drivers/gpu/drm/i915/display/intel_vbt_defs.h | 17 ++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index d32091dad1b0..9a14d55b636c 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -188,7 +188,7 @@ static const struct {
 	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
 	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
 	{ .section_id = BDB_LVDS_LFP_DATA,
-	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
+	  .min_size = 0, /* special case */ },
 	{ .section_id = BDB_LVDS_BACKLIGHT,
 	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
 	{ .section_id = BDB_LFP_POWER,
@@ -203,6 +203,23 @@ static const struct {
 	  .min_size = sizeof(struct bdb_generic_dtd), },
 };
 
+static size_t lfp_data_min_size(struct drm_i915_private *i915)
+{
+	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+	size_t size;
+
+	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
+	if (!ptrs)
+		return 0;
+
+	size = sizeof(struct bdb_lvds_lfp_data);
+	if (ptrs->panel_name.table_size)
+		size = max(size, ptrs->panel_name.offset +
+			   sizeof(struct bdb_lvds_lfp_data_tail));
+
+	return size;
+}
+
 static bool validate_lfp_data_ptrs(const void *bdb,
 				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
 {
@@ -492,6 +509,9 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
 		enum bdb_block_id section_id = bdb_blocks[i].section_id;
 		size_t min_size = bdb_blocks[i].min_size;
 
+		if (section_id == BDB_LVDS_LFP_DATA)
+			min_size = lfp_data_min_size(i915);
+
 		init_bdb_block(i915, bdb, section_id, min_size);
 	}
 }
@@ -562,6 +582,16 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
 	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
 }
 
+static const struct bdb_lvds_lfp_data_tail *
+get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
+		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
+{
+	if (ptrs->panel_name.table_size)
+		return (const void *)data + ptrs->panel_name.offset;
+	else
+		return NULL;
+}
+
 /* Parse general panel options */
 static void
 parse_panel_options(struct drm_i915_private *i915)
@@ -666,6 +696,7 @@ static void
 parse_lfp_data(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_lfp_data *data;
+	const struct bdb_lvds_lfp_data_tail *tail;
 	const struct bdb_lvds_lfp_data_ptrs *ptrs;
 
 	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
@@ -678,6 +709,12 @@ parse_lfp_data(struct drm_i915_private *i915)
 
 	if (!i915->vbt.lfp_lvds_vbt_mode)
 		parse_lfp_panel_dtd(i915, data, ptrs);
+
+	tail = get_lfp_data_tail(data, ptrs);
+	if (!tail)
+		return;
+
+	(void)tail;
 }
 
 static void
diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
index e4a11c3e3f3e..64551d206aeb 100644
--- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
+++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
@@ -783,6 +783,23 @@ struct lvds_lfp_panel_name {
 	u8 name[13];
 } __packed;
 
+struct lvds_lfp_black_border {
+	u8 top; /*  227 */
+	u8 bottom; /*  227 */
+	u8 left; /* 238 */
+	u8 right; /* 238 */
+} __packed;
+
+struct bdb_lvds_lfp_data_tail {
+	struct lvds_lfp_panel_name panel_name[16]; /* 156-163? */
+	u16 scaling_enable; /* 187 */
+	u8 seamless_drrs_min_refresh_rate[16]; /* 188 */
+	u8 pixel_overlap_count[16]; /* 208 */
+	struct lvds_lfp_black_border black_border[16]; /* 227 */
+	u16 dual_lfp_port_sync_enable; /* 231 */
+	u16 gpu_dithering_for_banding_artifacts; /* 245 */
+} __packed;
+
 /*
  * Block 43 - LFP Backlight Control Data Block
  */
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (25 preceding siblings ...)
  2022-04-05 23:27 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
@ 2022-04-06 18:17 ` Patchwork
  2022-04-06 18:19 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-06 18:17 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4)
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
b4e5171b664d drm/i915/bios: Use the cached BDB version
91a6a31d6e40 drm/i915/bios: Make copies of VBT data blocks
f84bede3e81c drm/i915/bios: Use the copy of the LFP data table always
30d47b4d1757 drm/i915/bios: Validate LFP data table pointers
-:93: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#93: FILE: drivers/gpu/drm/i915/display/intel_bios.c:257:
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||

-:93: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#93: FILE: drivers/gpu/drm/i915/display/intel_bios.c:257:
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
 		                                               ^

-:94: WARNING:LONG_LINE: line length of 105 exceeds 100 columns
#94: FILE: drivers/gpu/drm/i915/display/intel_bios.c:258:
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||

-:94: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#94: FILE: drivers/gpu/drm/i915/display/intel_bios.c:258:
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
 		                                                ^

-:95: WARNING:LONG_LINE: line length of 107 exceeds 100 columns
#95: FILE: drivers/gpu/drm/i915/display/intel_bios.c:259:
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)

-:95: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#95: FILE: drivers/gpu/drm/i915/display/intel_bios.c:259:
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
 		                                                  ^

total: 0 errors, 3 warnings, 3 checks, 100 lines checked
bed8bb53d49d drm/i915/bios: Trust the LFP data pointers
2e9070604964 drm/i915/bios: Validate the panel_name table
4b1cfd666e42 drm/i915/bios: Reorder panel DTD parsing
6797181190b9 drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
-:47: CHECK:SPACING: spaces preferred around that '+' (ctx:VxV)
#47: FILE: drivers/gpu/drm/i915/display/intel_bios.c:321:
+		if (data[i] == 0xff && data[i+1] == 0xff)
 		                             ^

-:134: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#134: FILE: drivers/gpu/drm/i915/display/intel_bios.c:408:
+		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
 		                                                       ^

-:135: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#135: FILE: drivers/gpu/drm/i915/display/intel_bios.c:409:
+		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
 		                                                        ^

-:136: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#136: FILE: drivers/gpu/drm/i915/display/intel_bios.c:410:
+		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
 		                                                          ^

total: 0 errors, 0 warnings, 4 checks, 163 lines checked
e54cf3e16a29 drm/i915/bios: Get access to the tail end of the LFP data block
718fdbd4b349 drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
16cec422aefa drm/i915/bios: Split parse_driver_features() into two parts
511de072181d drm/i915/bios: Split VBT parsing to global vs. panel specific parts
987ad104edba drm/i915/pps: Split PPS init+sanitize in two
135bb305bf0d drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
3afee78fe4c6 drm/i915/bios: Do panel specific VBT parsing later
082d08598bc3 drm/i915/bios: Extract get_panel_type()
7106a9b6a6d5 drm/i915/bios: Refactor panel_type code
5569057d6965 drm/i915/bios: Determine panel type via PNPID match
f21af8606c61 drm/i915/bios: Parse the seamless DRRS min refresh rate
f661fdbb6c91 drm/i915: Respect VBT seamless DRRS min refresh rate
3b81ff885960 drm/edid: Extract drm_edid_decode_mfg_id()
41cadc9f81e3 drm/i915/bios: Dump PNPID and panel name



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (26 preceding siblings ...)
  2022-04-06 18:17 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4) Patchwork
@ 2022-04-06 18:19 ` Patchwork
  2022-04-06 18:50 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-06 18:19 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4)
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (27 preceding siblings ...)
  2022-04-06 18:19 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2022-04-06 18:50 ` Patchwork
  2022-04-07  0:11 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6) Patchwork
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-06 18:50 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 7952 bytes --]

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4)
URL   : https://patchwork.freedesktop.org/series/102213/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11465 -> Patchwork_22797
====================================================

Summary
-------

  **WARNING**

  Minor unknown changes coming with Patchwork_22797 need to be verified
  manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_22797, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/index.html

Participating hosts (50 -> 43)
------------------------------

  Missing    (7): shard-tglu fi-bsw-cyan fi-ctg-p8600 fi-hsw-4770 fi-pnv-d510 bat-rpls-1 fi-bdw-samus 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22797:

### IGT changes ###

#### Warnings ####

  * igt@runner@aborted:
    - fi-bxt-dsi:         [FAIL][1] ([i915#4312] / [i915#5257]) -> [FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/fi-bxt-dsi/igt@runner@aborted.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/fi-bxt-dsi/igt@runner@aborted.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * igt@gem_lmem_swapping@verify-random:
    - {bat-dg2-9}:        NOTRUN -> [FAIL][3]
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/bat-dg2-9/igt@gem_lmem_swapping@verify-random.html

  * igt@gem_ringfill@basic-all:
    - {bat-dg2-8}:        [PASS][4] -> [TIMEOUT][5]
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/bat-dg2-8/igt@gem_ringfill@basic-all.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/bat-dg2-8/igt@gem_ringfill@basic-all.html

  * igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b:
    - {bat-adlp-6}:       [DMESG-WARN][6] ([i915#3576]) -> [DMESG-WARN][7]
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/bat-adlp-6/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/bat-adlp-6/igt@kms_pipe_crc_basic@compare-crc-sanitycheck-pipe-b.html

  
Known issues
------------

  Here are the changes found in Patchwork_22797 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_exec_suspend@basic-s3@smem:
    - fi-bdw-5557u:       [PASS][8] -> [INCOMPLETE][9] ([i915#146])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/fi-bdw-5557u/igt@gem_exec_suspend@basic-s3@smem.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/fi-bdw-5557u/igt@gem_exec_suspend@basic-s3@smem.html

  * igt@i915_selftest@live@hangcheck:
    - fi-snb-2600:        [PASS][10] -> [INCOMPLETE][11] ([i915#3921])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/fi-snb-2600/igt@i915_selftest@live@hangcheck.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/fi-snb-2600/igt@i915_selftest@live@hangcheck.html

  
#### Possible fixes ####

  * igt@kms_flip@basic-flip-vs-modeset@a-edp1:
    - {bat-adlp-6}:       [DMESG-WARN][12] ([i915#3576]) -> [PASS][13]
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/bat-adlp-6/igt@kms_flip@basic-flip-vs-modeset@a-edp1.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/bat-adlp-6/igt@kms_flip@basic-flip-vs-modeset@a-edp1.html

  
#### Warnings ####

  * igt@core_hotunplug@unbind-rebind:
    - fi-kbl-7567u:       [DMESG-WARN][14] -> [DMESG-WARN][15] ([i915#5437])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11465/fi-kbl-7567u/igt@core_hotunplug@unbind-rebind.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/fi-kbl-7567u/igt@core_hotunplug@unbind-rebind.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109285]: https://bugs.freedesktop.org/show_bug.cgi?id=109285
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1072]: https://gitlab.freedesktop.org/drm/intel/issues/1072
  [i915#1155]: https://gitlab.freedesktop.org/drm/intel/issues/1155
  [i915#146]: https://gitlab.freedesktop.org/drm/intel/issues/146
  [i915#3291]: https://gitlab.freedesktop.org/drm/intel/issues/3291
  [i915#3555]: https://gitlab.freedesktop.org/drm/intel/issues/3555
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#3595]: https://gitlab.freedesktop.org/drm/intel/issues/3595
  [i915#3708]: https://gitlab.freedesktop.org/drm/intel/issues/3708
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#4077]: https://gitlab.freedesktop.org/drm/intel/issues/4077
  [i915#4079]: https://gitlab.freedesktop.org/drm/intel/issues/4079
  [i915#4083]: https://gitlab.freedesktop.org/drm/intel/issues/4083
  [i915#4103]: https://gitlab.freedesktop.org/drm/intel/issues/4103
  [i915#4212]: https://gitlab.freedesktop.org/drm/intel/issues/4212
  [i915#4213]: https://gitlab.freedesktop.org/drm/intel/issues/4213
  [i915#4215]: https://gitlab.freedesktop.org/drm/intel/issues/4215
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4873]: https://gitlab.freedesktop.org/drm/intel/issues/4873
  [i915#5190]: https://gitlab.freedesktop.org/drm/intel/issues/5190
  [i915#5193]: https://gitlab.freedesktop.org/drm/intel/issues/5193
  [i915#5195]: https://gitlab.freedesktop.org/drm/intel/issues/5195
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5274]: https://gitlab.freedesktop.org/drm/intel/issues/5274
  [i915#5275]: https://gitlab.freedesktop.org/drm/intel/issues/5275
  [i915#5437]: https://gitlab.freedesktop.org/drm/intel/issues/5437


Build changes
-------------

  * Linux: CI_DRM_11465 -> Patchwork_22797

  CI-20190529: 20190529
  CI_DRM_11465: ffe5d6a4b92fb26e9067efb1278fb58c9af68628 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6413: 7506029428b3740395ce086daf86b9498fbbeb77 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22797: 41cadc9f81e3e56772cead934324d861d1bc6c61 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

41cadc9f81e3 drm/i915/bios: Dump PNPID and panel name
3b81ff885960 drm/edid: Extract drm_edid_decode_mfg_id()
f661fdbb6c91 drm/i915: Respect VBT seamless DRRS min refresh rate
f21af8606c61 drm/i915/bios: Parse the seamless DRRS min refresh rate
5569057d6965 drm/i915/bios: Determine panel type via PNPID match
7106a9b6a6d5 drm/i915/bios: Refactor panel_type code
082d08598bc3 drm/i915/bios: Extract get_panel_type()
3afee78fe4c6 drm/i915/bios: Do panel specific VBT parsing later
135bb305bf0d drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
987ad104edba drm/i915/pps: Split PPS init+sanitize in two
511de072181d drm/i915/bios: Split VBT parsing to global vs. panel specific parts
16cec422aefa drm/i915/bios: Split parse_driver_features() into two parts
718fdbd4b349 drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
e54cf3e16a29 drm/i915/bios: Get access to the tail end of the LFP data block
6797181190b9 drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
4b1cfd666e42 drm/i915/bios: Reorder panel DTD parsing
2e9070604964 drm/i915/bios: Validate the panel_name table
bed8bb53d49d drm/i915/bios: Trust the LFP data pointers
30d47b4d1757 drm/i915/bios: Validate LFP data table pointers
f84bede3e81c drm/i915/bios: Use the copy of the LFP data table always
91a6a31d6e40 drm/i915/bios: Make copies of VBT data blocks
b4e5171b664d drm/i915/bios: Use the cached BDB version

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22797/index.html

[-- Attachment #2: Type: text/html, Size: 7547 bytes --]

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v4 15/22] drm/i915/bios: Do panel specific VBT parsing later
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 15/22] drm/i915/bios: Do panel specific VBT parsing later Ville Syrjala
@ 2022-04-06 19:05   ` Ville Syrjala
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjala @ 2022-04-06 19:05 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Move the panel specific VBT parsing to happen during the
output probing stage. Needs to be done because the VBT
parsing will need to look at the EDID to determine
the correct panel_type on some machines.

v2: Do intel_bios_init_panel() a bit earlier for vlv_dsi

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/icl_dsi.c       | 2 ++
 drivers/gpu/drm/i915/display/intel_display.c | 1 -
 drivers/gpu/drm/i915/display/intel_dp.c      | 2 ++
 drivers/gpu/drm/i915/display/intel_lvds.c    | 2 ++
 drivers/gpu/drm/i915/display/intel_sdvo.c    | 3 +++
 drivers/gpu/drm/i915/display/vlv_dsi.c       | 2 ++
 6 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 084cc51d1c41..688176d4a54a 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -2048,6 +2048,8 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
 	/* attach connector to encoder */
 	intel_connector_attach_encoder(intel_connector, encoder);
 
+	intel_bios_init_panel(dev_priv);
+
 	mutex_lock(&dev->mode_config.mutex);
 	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
 	mutex_unlock(&dev->mode_config.mutex);
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 4ece4e7d0296..eee185ed41c3 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -9650,7 +9650,6 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
 	}
 
 	intel_bios_init(i915);
-	intel_bios_init_panel(i915);
 
 	ret = intel_vga_register(i915);
 	if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 7249b988592d..a1b5d7f5388b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5179,6 +5179,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	intel_connector->edid = edid;
 
+	intel_bios_init_panel(dev_priv);
+
 	intel_panel_add_edid_fixed_modes(intel_connector,
 					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
 
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index e8478161f8b9..554badf041f2 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -967,6 +967,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
 	}
 	intel_connector->edid = edid;
 
+	intel_bios_init_panel(dev_priv);
+
 	/* Try EDID first */
 	intel_panel_add_edid_fixed_modes(intel_connector,
 					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index ab88d8b783e6..661a1057a073 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2868,6 +2868,7 @@ static bool
 intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 {
 	struct drm_encoder *encoder = &intel_sdvo->base.base;
+	struct drm_i915_private *i915 = to_i915(encoder->dev);
 	struct drm_connector *connector;
 	struct intel_connector *intel_connector;
 	struct intel_sdvo_connector *intel_sdvo_connector;
@@ -2899,6 +2900,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
 		goto err;
 
+	intel_bios_init_panel(i915);
+
 	/*
 	 * Fetch modes from VBT. For SDVO prefer the VBT mode since some
 	 * SDVO->LVDS transcoders can't cope with the EDID mode.
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 1954f07f0d3e..08fb554ff7ad 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1929,6 +1929,8 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
 	else
 		intel_dsi->ports = BIT(port);
 
+	intel_bios_init_panel(dev_priv);
+
 	intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports;
 	intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports;
 
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] [PATCH v4 18/22] drm/i915/bios: Determine panel type via PNPID match
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 18/22] drm/i915/bios: Determine panel type via PNPID match Ville Syrjala
@ 2022-04-06 19:09   ` Ville Syrjala
  2022-04-07 17:55     ` Jani Nikula
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjala @ 2022-04-06 19:09 UTC (permalink / raw)
  To: intel-gfx

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Apparently when the VBT panel_type==0xff we should trawl through
the PNPID table and check for a match against the EDID. If a
match is found the index gives us the panel_type.

Tried to match the Windows behaviour here with first looking
for an exact match, and if one isn't found we fall back to
looking for a match w/o the mfg year/week.

v2: Rebase due to vlv_dsi changes

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5545
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/display/icl_dsi.c    |  2 +-
 drivers/gpu/drm/i915/display/intel_bios.c | 82 ++++++++++++++++++++---
 drivers/gpu/drm/i915/display/intel_bios.h |  4 +-
 drivers/gpu/drm/i915/display/intel_dp.c   |  2 +-
 drivers/gpu/drm/i915/display/intel_lvds.c |  2 +-
 drivers/gpu/drm/i915/display/intel_sdvo.c |  2 +-
 drivers/gpu/drm/i915/display/vlv_dsi.c    |  2 +-
 7 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index 688176d4a54a..49715485a3a6 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -2048,7 +2048,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
 	/* attach connector to encoder */
 	intel_connector_attach_encoder(intel_connector, encoder);
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, NULL);
 
 	mutex_lock(&dev->mode_config.mutex);
 	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 0e76c554581a..4c0680356134 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -582,6 +582,14 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
 	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
 }
 
+static const struct lvds_pnp_id *
+get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data,
+		const struct bdb_lvds_lfp_data_ptrs *ptrs,
+		int index)
+{
+	return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset;
+}
+
 static const struct bdb_lvds_lfp_data_tail *
 get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
 		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
@@ -592,6 +600,52 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
 		return NULL;
 }
 
+static int pnp_id_panel_type(struct drm_i915_private *i915,
+			     const struct edid *edid)
+{
+	const struct bdb_lvds_lfp_data *data;
+	const struct bdb_lvds_lfp_data_ptrs *ptrs;
+	const struct lvds_pnp_id *edid_id;
+	struct lvds_pnp_id edid_id_nodate;
+	int i, best = -1;
+
+	if (!edid)
+		return -1;
+
+	edid_id = (const void *)&edid->mfg_id[0];
+
+	edid_id_nodate = *edid_id;
+	edid_id_nodate.mfg_week = 0;
+	edid_id_nodate.mfg_year = 0;
+
+	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
+	if (!ptrs)
+		return -1;
+
+	data = find_section(i915, BDB_LVDS_LFP_DATA);
+	if (!data)
+		return -1;
+
+	for (i = 0; i < 16; i++) {
+		const struct lvds_pnp_id *vbt_id =
+			get_lvds_pnp_id(data, ptrs, i);
+
+		/* full match? */
+		if (!memcmp(vbt_id, edid_id, sizeof(*vbt_id)))
+			return i;
+
+		/*
+		 * Accept a match w/o date if no full match is found,
+		 * and the VBT entry does not specify a date.
+		 */
+		if (best < 0 &&
+		    !memcmp(vbt_id, &edid_id_nodate, sizeof(*vbt_id)))
+			best = i;
+	}
+
+	return best;
+}
+
 static int vbt_panel_type(struct drm_i915_private *i915)
 {
 	const struct bdb_lvds_options *lvds_options;
@@ -600,7 +654,8 @@ static int vbt_panel_type(struct drm_i915_private *i915)
 	if (!lvds_options)
 		return -1;
 
-	if (lvds_options->panel_type > 0xf) {
+	if (lvds_options->panel_type > 0xf &&
+	    lvds_options->panel_type != 0xff) {
 		drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n",
 			    lvds_options->panel_type);
 		return -1;
@@ -612,10 +667,12 @@ static int vbt_panel_type(struct drm_i915_private *i915)
 enum panel_type {
 	PANEL_TYPE_OPREGION,
 	PANEL_TYPE_VBT,
+	PANEL_TYPE_PNPID,
 	PANEL_TYPE_FALLBACK,
 };
 
-static int get_panel_type(struct drm_i915_private *i915)
+static int get_panel_type(struct drm_i915_private *i915,
+			  const struct edid *edid)
 {
 	struct {
 		const char *name;
@@ -623,15 +680,18 @@ static int get_panel_type(struct drm_i915_private *i915)
 	} panel_types[] = {
 		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
 		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
+		[PANEL_TYPE_PNPID] = { .name = "PNPID", .panel_type = -1, },
 		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
 	};
 	int i;
 
 	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
 	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);
+	panel_types[PANEL_TYPE_PNPID].panel_type = pnp_id_panel_type(i915, edid);
 
 	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
-		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);
+		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf &&
+			    panel_types[i].panel_type != 0xff);
 
 		if (panel_types[i].panel_type >= 0)
 			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
@@ -640,7 +700,11 @@ static int get_panel_type(struct drm_i915_private *i915)
 
 	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
 		i = PANEL_TYPE_OPREGION;
-	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
+	else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
+		 panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
+		i = PANEL_TYPE_PNPID;
+	else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
+		 panel_types[PANEL_TYPE_VBT].panel_type >= 0)
 		i = PANEL_TYPE_VBT;
 	else
 		i = PANEL_TYPE_FALLBACK;
@@ -653,7 +717,8 @@ static int get_panel_type(struct drm_i915_private *i915)
 
 /* Parse general panel options */
 static void
-parse_panel_options(struct drm_i915_private *i915)
+parse_panel_options(struct drm_i915_private *i915,
+		    const struct edid *edid)
 {
 	const struct bdb_lvds_options *lvds_options;
 	int panel_type;
@@ -665,7 +730,7 @@ parse_panel_options(struct drm_i915_private *i915)
 
 	i915->vbt.lvds_dither = lvds_options->pixel_dither;
 
-	panel_type = get_panel_type(i915);
+	panel_type = get_panel_type(i915, edid);
 
 	i915->vbt.panel_type = panel_type;
 
@@ -2953,9 +3018,10 @@ void intel_bios_init(struct drm_i915_private *i915)
 	kfree(oprom_vbt);
 }
 
-void intel_bios_init_panel(struct drm_i915_private *i915)
+void intel_bios_init_panel(struct drm_i915_private *i915,
+			   const struct edid *edid)
 {
-	parse_panel_options(i915);
+	parse_panel_options(i915, edid);
 	/*
 	 * Older VBTs provided DTD information for internal displays through
 	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
index c744d75fa435..be6d57bd0f5a 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.h
+++ b/drivers/gpu/drm/i915/display/intel_bios.h
@@ -33,6 +33,7 @@
 #include <linux/types.h>
 
 struct drm_i915_private;
+struct edid;
 struct intel_bios_encoder_data;
 struct intel_crtc_state;
 struct intel_encoder;
@@ -230,7 +231,8 @@ struct mipi_pps_data {
 } __packed;
 
 void intel_bios_init(struct drm_i915_private *dev_priv);
-void intel_bios_init_panel(struct drm_i915_private *dev_priv);
+void intel_bios_init_panel(struct drm_i915_private *dev_priv,
+			   const struct edid *edid);
 void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
 bool intel_bios_is_valid_vbt(const void *buf, size_t size);
 bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a1b5d7f5388b..41ac55a700e9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -5179,7 +5179,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 	intel_connector->edid = edid;
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
 
 	intel_panel_add_edid_fixed_modes(intel_connector,
 					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index 554badf041f2..660bb95f2bf7 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -967,7 +967,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
 	}
 	intel_connector->edid = edid;
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
 
 	/* Try EDID first */
 	intel_panel_add_edid_fixed_modes(intel_connector,
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index 661a1057a073..25195bc1edca 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -2900,7 +2900,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
 	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
 		goto err;
 
-	intel_bios_init_panel(i915);
+	intel_bios_init_panel(i915, NULL);
 
 	/*
 	 * Fetch modes from VBT. For SDVO prefer the VBT mode since some
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index 08fb554ff7ad..1af6e927af9b 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -1929,7 +1929,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
 	else
 		intel_dsi->ports = BIT(port);
 
-	intel_bios_init_panel(dev_priv);
+	intel_bios_init_panel(dev_priv, NULL);
 
 	intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports;
 	intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports;
-- 
2.35.1


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (28 preceding siblings ...)
  2022-04-06 18:50 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2022-04-07  0:11 ` Patchwork
  2022-04-07  0:14 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-07  0:11 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
fdfc2be08fd7 drm/i915/bios: Use the cached BDB version
8dc5af439d5d drm/i915/bios: Make copies of VBT data blocks
672b309530c4 drm/i915/bios: Use the copy of the LFP data table always
4cfe7896f554 drm/i915/bios: Validate LFP data table pointers
-:93: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#93: FILE: drivers/gpu/drm/i915/display/intel_bios.c:257:
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||

-:93: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#93: FILE: drivers/gpu/drm/i915/display/intel_bios.c:257:
+		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
 		                                               ^

-:94: WARNING:LONG_LINE: line length of 105 exceeds 100 columns
#94: FILE: drivers/gpu/drm/i915/display/intel_bios.c:258:
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||

-:94: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#94: FILE: drivers/gpu/drm/i915/display/intel_bios.c:258:
+		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
 		                                                ^

-:95: WARNING:LONG_LINE: line length of 107 exceeds 100 columns
#95: FILE: drivers/gpu/drm/i915/display/intel_bios.c:259:
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)

-:95: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#95: FILE: drivers/gpu/drm/i915/display/intel_bios.c:259:
+		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
 		                                                  ^

total: 0 errors, 3 warnings, 3 checks, 100 lines checked
9d8c9b4008e5 drm/i915/bios: Trust the LFP data pointers
e7a5932867a6 drm/i915/bios: Validate the panel_name table
352847c0e8b3 drm/i915/bios: Reorder panel DTD parsing
cf38814a8c6c drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
-:47: CHECK:SPACING: spaces preferred around that '+' (ctx:VxV)
#47: FILE: drivers/gpu/drm/i915/display/intel_bios.c:321:
+		if (data[i] == 0xff && data[i+1] == 0xff)
 		                             ^

-:134: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#134: FILE: drivers/gpu/drm/i915/display/intel_bios.c:408:
+		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
 		                                                       ^

-:135: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#135: FILE: drivers/gpu/drm/i915/display/intel_bios.c:409:
+		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
 		                                                        ^

-:136: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#136: FILE: drivers/gpu/drm/i915/display/intel_bios.c:410:
+		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
 		                                                          ^

total: 0 errors, 0 warnings, 4 checks, 163 lines checked
88f348858b05 drm/i915/bios: Get access to the tail end of the LFP data block
77fbdc1340cb drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
d09cde4bafdd drm/i915/bios: Split parse_driver_features() into two parts
d2557a522b00 drm/i915/bios: Split VBT parsing to global vs. panel specific parts
f3f6fd93b1d9 drm/i915/pps: Split PPS init+sanitize in two
ee0b015fb8b5 drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
1f699fc7080d drm/i915/bios: Do panel specific VBT parsing later
99290a9ac023 drm/i915/bios: Extract get_panel_type()
bdb3831d1ec8 drm/i915/bios: Refactor panel_type code
98e3b7bd98d0 drm/i915/bios: Determine panel type via PNPID match
409a939b51b8 drm/i915/bios: Parse the seamless DRRS min refresh rate
1ec0c835042e drm/i915: Respect VBT seamless DRRS min refresh rate
b05a19342dcb drm/edid: Extract drm_edid_decode_mfg_id()
9f80bf52f53a drm/i915/bios: Dump PNPID and panel name



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (29 preceding siblings ...)
  2022-04-07  0:11 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6) Patchwork
@ 2022-04-07  0:14 ` Patchwork
  2022-04-07  0:44 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
  2022-04-07  8:37 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-07  0:14 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
URL   : https://patchwork.freedesktop.org/series/102213/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (30 preceding siblings ...)
  2022-04-07  0:14 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2022-04-07  0:44 ` Patchwork
  2022-04-07  8:37 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-07  0:44 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 5872 bytes --]

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
URL   : https://patchwork.freedesktop.org/series/102213/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11467 -> Patchwork_22801
====================================================

Summary
-------

  **WARNING**

  Minor unknown changes coming with Patchwork_22801 need to be verified
  manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_22801, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/index.html

Participating hosts (51 -> 44)
------------------------------

  Missing    (7): shard-tglu fi-bsw-cyan bat-adlp-4 fi-ctg-p8600 fi-hsw-4770 shard-rkl fi-bdw-samus 

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_22801:

### IGT changes ###

#### Warnings ####

  * igt@runner@aborted:
    - fi-bxt-dsi:         [FAIL][1] ([i915#4312] / [i915#5257]) -> [FAIL][2]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/fi-bxt-dsi/igt@runner@aborted.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/fi-bxt-dsi/igt@runner@aborted.html

  
Known issues
------------

  Here are the changes found in Patchwork_22801 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@i915_selftest@live@hangcheck:
    - fi-bdw-5557u:       NOTRUN -> [INCOMPLETE][3] ([i915#3921])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/fi-bdw-5557u/igt@i915_selftest@live@hangcheck.html

  * igt@kms_chamelium@vga-edid-read:
    - fi-bdw-5557u:       NOTRUN -> [SKIP][4] ([fdo#109271] / [fdo#111827]) +8 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/fi-bdw-5557u/igt@kms_chamelium@vga-edid-read.html

  * igt@kms_setmode@basic-clone-single-crtc:
    - fi-bdw-5557u:       NOTRUN -> [SKIP][5] ([fdo#109271]) +14 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/fi-bdw-5557u/igt@kms_setmode@basic-clone-single-crtc.html
    - fi-snb-2600:        NOTRUN -> [SKIP][6] ([fdo#109271])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/fi-snb-2600/igt@kms_setmode@basic-clone-single-crtc.html

  
#### Possible fixes ####

  * igt@i915_pm_rps@basic-api:
    - bat-dg1-6:          [FAIL][7] ([i915#4032]) -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/bat-dg1-6/igt@i915_pm_rps@basic-api.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/bat-dg1-6/igt@i915_pm_rps@basic-api.html

  
#### Warnings ####

  * igt@core_hotunplug@unbind-rebind:
    - fi-kbl-soraka:      [DMESG-WARN][9] ([i915#5437]) -> [DMESG-WARN][10] ([i915#1982] / [i915#5437])
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/fi-kbl-soraka/igt@core_hotunplug@unbind-rebind.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/fi-kbl-soraka/igt@core_hotunplug@unbind-rebind.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1982]: https://gitlab.freedesktop.org/drm/intel/issues/1982
  [i915#3576]: https://gitlab.freedesktop.org/drm/intel/issues/3576
  [i915#3921]: https://gitlab.freedesktop.org/drm/intel/issues/3921
  [i915#4032]: https://gitlab.freedesktop.org/drm/intel/issues/4032
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#5257]: https://gitlab.freedesktop.org/drm/intel/issues/5257
  [i915#5437]: https://gitlab.freedesktop.org/drm/intel/issues/5437


Build changes
-------------

  * Linux: CI_DRM_11467 -> Patchwork_22801

  CI-20190529: 20190529
  CI_DRM_11467: 9620d9a4dee7a4c418de2683f3a7f544042c1a4a @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_6414: b4d8d30a4ec8dae5c1c403f41348c073a9591d9f @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  Patchwork_22801: 9f80bf52f53a59940c439d4f636489e6ae56a127 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

9f80bf52f53a drm/i915/bios: Dump PNPID and panel name
b05a19342dcb drm/edid: Extract drm_edid_decode_mfg_id()
1ec0c835042e drm/i915: Respect VBT seamless DRRS min refresh rate
409a939b51b8 drm/i915/bios: Parse the seamless DRRS min refresh rate
98e3b7bd98d0 drm/i915/bios: Determine panel type via PNPID match
bdb3831d1ec8 drm/i915/bios: Refactor panel_type code
99290a9ac023 drm/i915/bios: Extract get_panel_type()
1f699fc7080d drm/i915/bios: Do panel specific VBT parsing later
ee0b015fb8b5 drm/i915/pps: Reinit PPS delays after VBT has been fully parsed
f3f6fd93b1d9 drm/i915/pps: Split PPS init+sanitize in two
d2557a522b00 drm/i915/bios: Split VBT parsing to global vs. panel specific parts
d09cde4bafdd drm/i915/bios: Split parse_driver_features() into two parts
77fbdc1340cb drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
88f348858b05 drm/i915/bios: Get access to the tail end of the LFP data block
cf38814a8c6c drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
352847c0e8b3 drm/i915/bios: Reorder panel DTD parsing
e7a5932867a6 drm/i915/bios: Validate the panel_name table
9d8c9b4008e5 drm/i915/bios: Trust the LFP data pointers
4cfe7896f554 drm/i915/bios: Validate LFP data table pointers
672b309530c4 drm/i915/bios: Use the copy of the LFP data table always
8dc5af439d5d drm/i915/bios: Make copies of VBT data blocks
fdfc2be08fd7 drm/i915/bios: Use the cached BDB version

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/index.html

[-- Attachment #2: Type: text/html, Size: 6899 bytes --]

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [Intel-gfx] ✓ Fi.CI.IGT: success for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
  2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
                   ` (31 preceding siblings ...)
  2022-04-07  0:44 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2022-04-07  8:37 ` Patchwork
  32 siblings, 0 replies; 72+ messages in thread
From: Patchwork @ 2022-04-07  8:37 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

[-- Attachment #1: Type: text/plain, Size: 30302 bytes --]

== Series Details ==

Series: drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6)
URL   : https://patchwork.freedesktop.org/series/102213/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11467_full -> Patchwork_22801_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  

Participating hosts (13 -> 13)
------------------------------

  No changes in participating hosts

Known issues
------------

  Here are the changes found in Patchwork_22801_full that come from known issues:

### CI changes ###

#### Issues hit ####

  * boot:
    - shard-glk:          ([PASS][1], [PASS][2], [PASS][3], [PASS][4], [PASS][5], [PASS][6], [PASS][7], [PASS][8], [PASS][9], [PASS][10], [PASS][11], [PASS][12], [PASS][13], [PASS][14], [PASS][15], [PASS][16], [PASS][17], [PASS][18], [PASS][19], [PASS][20], [PASS][21], [PASS][22], [PASS][23], [PASS][24], [PASS][25]) -> ([PASS][26], [PASS][27], [PASS][28], [PASS][29], [PASS][30], [FAIL][31], [PASS][32], [PASS][33], [PASS][34], [PASS][35], [PASS][36], [PASS][37], [PASS][38], [PASS][39], [PASS][40], [PASS][41], [PASS][42], [PASS][43], [PASS][44], [PASS][45], [PASS][46], [PASS][47], [PASS][48], [PASS][49], [PASS][50]) ([i915#4392])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk9/boot.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk9/boot.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk9/boot.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk8/boot.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk8/boot.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk8/boot.html
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk7/boot.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk7/boot.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk7/boot.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk7/boot.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk6/boot.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk6/boot.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk6/boot.html
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk5/boot.html
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk5/boot.html
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk5/boot.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk4/boot.html
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk4/boot.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk4/boot.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk3/boot.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk3/boot.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk2/boot.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk2/boot.html
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk1/boot.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk1/boot.html
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk1/boot.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk1/boot.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk1/boot.html
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk2/boot.html
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk2/boot.html
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk2/boot.html
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk2/boot.html
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk3/boot.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk3/boot.html
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk3/boot.html
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk4/boot.html
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk4/boot.html
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk4/boot.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk5/boot.html
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk5/boot.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk5/boot.html
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk6/boot.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk6/boot.html
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk6/boot.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk7/boot.html
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk7/boot.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk8/boot.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk8/boot.html
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk9/boot.html
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk9/boot.html

  

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_persistence@many-contexts:
    - shard-tglb:         [PASS][51] -> [FAIL][52] ([i915#2410])
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-tglb7/igt@gem_ctx_persistence@many-contexts.html
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb1/igt@gem_ctx_persistence@many-contexts.html

  * igt@gem_exec_endless@dispatch@vcs1:
    - shard-iclb:         NOTRUN -> [INCOMPLETE][53] ([i915#3778])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb1/igt@gem_exec_endless@dispatch@vcs1.html

  * igt@gem_exec_fair@basic-deadline:
    - shard-skl:          NOTRUN -> [FAIL][54] ([i915#2846])
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl4/igt@gem_exec_fair@basic-deadline.html

  * igt@gem_exec_fair@basic-none-share@rcs0:
    - shard-tglb:         [PASS][55] -> [FAIL][56] ([i915#2842])
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-tglb6/igt@gem_exec_fair@basic-none-share@rcs0.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb6/igt@gem_exec_fair@basic-none-share@rcs0.html

  * igt@gem_exec_fair@basic-none-vip@rcs0:
    - shard-kbl:          [PASS][57] -> [FAIL][58] ([i915#2842])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-kbl1/igt@gem_exec_fair@basic-none-vip@rcs0.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-kbl6/igt@gem_exec_fair@basic-none-vip@rcs0.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-glk:          [PASS][59] -> [FAIL][60] ([i915#2842])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk3/igt@gem_exec_fair@basic-none@vcs0.html
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk1/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_flush@basic-batch-kernel-default-wb:
    - shard-snb:          [PASS][61] -> [SKIP][62] ([fdo#109271]) +1 similar issue
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-snb7/igt@gem_exec_flush@basic-batch-kernel-default-wb.html
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-snb6/igt@gem_exec_flush@basic-batch-kernel-default-wb.html

  * igt@gem_exec_params@secure-non-root:
    - shard-tglb:         NOTRUN -> [SKIP][63] ([fdo#112283])
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@gem_exec_params@secure-non-root.html
    - shard-iclb:         NOTRUN -> [SKIP][64] ([fdo#112283])
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@gem_exec_params@secure-non-root.html

  * igt@gem_lmem_swapping@random:
    - shard-tglb:         NOTRUN -> [SKIP][65] ([i915#4613])
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@gem_lmem_swapping@random.html
    - shard-skl:          NOTRUN -> [SKIP][66] ([fdo#109271] / [i915#4613])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl4/igt@gem_lmem_swapping@random.html
    - shard-iclb:         NOTRUN -> [SKIP][67] ([i915#4613])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@gem_lmem_swapping@random.html

  * igt@gem_pxp@create-protected-buffer:
    - shard-iclb:         NOTRUN -> [SKIP][68] ([i915#4270])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@gem_pxp@create-protected-buffer.html
    - shard-tglb:         NOTRUN -> [SKIP][69] ([i915#4270])
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@gem_pxp@create-protected-buffer.html

  * igt@gem_render_copy@y-tiled-mc-ccs-to-vebox-y-tiled:
    - shard-iclb:         NOTRUN -> [SKIP][70] ([i915#768])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@gem_render_copy@y-tiled-mc-ccs-to-vebox-y-tiled.html

  * igt@gen9_exec_parse@cmd-crossing-page:
    - shard-tglb:         NOTRUN -> [SKIP][71] ([i915#2527] / [i915#2856])
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@gen9_exec_parse@cmd-crossing-page.html
    - shard-iclb:         NOTRUN -> [SKIP][72] ([i915#2856])
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@gen9_exec_parse@cmd-crossing-page.html

  * igt@i915_pm_sseu@full-enable:
    - shard-iclb:         NOTRUN -> [SKIP][73] ([i915#4387])
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@i915_pm_sseu@full-enable.html

  * igt@i915_selftest@live@hangcheck:
    - shard-snb:          [PASS][74] -> [INCOMPLETE][75] ([i915#3921])
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-snb7/igt@i915_selftest@live@hangcheck.html
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-snb7/igt@i915_selftest@live@hangcheck.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip:
    - shard-tglb:         NOTRUN -> [SKIP][76] ([i915#5286]) +1 similar issue
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@kms_big_fb@4-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip.html

  * igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip:
    - shard-iclb:         NOTRUN -> [SKIP][77] ([i915#5286]) +1 similar issue
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_big_fb@4-tiled-max-hw-stride-64bpp-rotate-0-async-flip.html

  * igt@kms_big_fb@x-tiled-16bpp-rotate-270:
    - shard-iclb:         NOTRUN -> [SKIP][78] ([fdo#110725] / [fdo#111614])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_big_fb@x-tiled-16bpp-rotate-270.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip:
    - shard-tglb:         NOTRUN -> [SKIP][79] ([fdo#111615])
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip-async-flip.html

  * igt@kms_ccs@pipe-b-bad-rotation-90-y_tiled_gen12_rc_ccs_cc:
    - shard-iclb:         NOTRUN -> [SKIP][80] ([fdo#109278] / [i915#3886])
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_ccs@pipe-b-bad-rotation-90-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_color@pipe-d-ctm-negative:
    - shard-kbl:          NOTRUN -> [SKIP][81] ([fdo#109271]) +16 similar issues
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-kbl1/igt@kms_color@pipe-d-ctm-negative.html

  * igt@kms_color_chamelium@pipe-c-ctm-0-5:
    - shard-iclb:         NOTRUN -> [SKIP][82] ([fdo#109284] / [fdo#111827]) +1 similar issue
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_color_chamelium@pipe-c-ctm-0-5.html
    - shard-skl:          NOTRUN -> [SKIP][83] ([fdo#109271] / [fdo#111827])
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl4/igt@kms_color_chamelium@pipe-c-ctm-0-5.html
    - shard-tglb:         NOTRUN -> [SKIP][84] ([fdo#109284] / [fdo#111827])
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@kms_color_chamelium@pipe-c-ctm-0-5.html

  * igt@kms_color_chamelium@pipe-c-degamma:
    - shard-apl:          NOTRUN -> [SKIP][85] ([fdo#109271] / [fdo#111827]) +1 similar issue
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-apl4/igt@kms_color_chamelium@pipe-c-degamma.html
    - shard-kbl:          NOTRUN -> [SKIP][86] ([fdo#109271] / [fdo#111827]) +1 similar issue
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-kbl1/igt@kms_color_chamelium@pipe-c-degamma.html

  * igt@kms_cursor_crc@pipe-a-cursor-512x170-random:
    - shard-tglb:         NOTRUN -> [SKIP][87] ([fdo#109279] / [i915#3359])
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@kms_cursor_crc@pipe-a-cursor-512x170-random.html
    - shard-iclb:         NOTRUN -> [SKIP][88] ([fdo#109278] / [fdo#109279])
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_cursor_crc@pipe-a-cursor-512x170-random.html

  * igt@kms_cursor_crc@pipe-d-cursor-32x10-onscreen:
    - shard-tglb:         NOTRUN -> [SKIP][89] ([i915#3359])
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@kms_cursor_crc@pipe-d-cursor-32x10-onscreen.html

  * igt@kms_cursor_crc@pipe-d-cursor-64x64-rapid-movement:
    - shard-iclb:         NOTRUN -> [SKIP][90] ([fdo#109278]) +9 similar issues
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_cursor_crc@pipe-d-cursor-64x64-rapid-movement.html

  * igt@kms_cursor_legacy@cursorb-vs-flipb-atomic-transitions-varying-size:
    - shard-iclb:         NOTRUN -> [SKIP][91] ([fdo#109274] / [fdo#109278])
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_cursor_legacy@cursorb-vs-flipb-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-glk:          [PASS][92] -> [FAIL][93] ([i915#2346])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk1/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk6/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_flip@2x-nonexisting-fb:
    - shard-iclb:         NOTRUN -> [SKIP][94] ([fdo#109274]) +1 similar issue
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_flip@2x-nonexisting-fb.html

  * igt@kms_flip@flip-vs-suspend@b-dp1:
    - shard-apl:          [PASS][95] -> [DMESG-WARN][96] ([i915#180]) +1 similar issue
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-apl7/igt@kms_flip@flip-vs-suspend@b-dp1.html
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-apl2/igt@kms_flip@flip-vs-suspend@b-dp1.html

  * igt@kms_flip@plain-flip-fb-recreate-interruptible@b-edp1:
    - shard-skl:          [PASS][97] -> [FAIL][98] ([i915#2122]) +1 similar issue
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-skl7/igt@kms_flip@plain-flip-fb-recreate-interruptible@b-edp1.html
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl7/igt@kms_flip@plain-flip-fb-recreate-interruptible@b-edp1.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite:
    - shard-skl:          NOTRUN -> [SKIP][99] ([fdo#109271]) +7 similar issues
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl4/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite.html
    - shard-tglb:         NOTRUN -> [SKIP][100] ([fdo#109280] / [fdo#111825]) +4 similar issues
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-pri-indfb-draw-pwrite.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-wc:
    - shard-iclb:         NOTRUN -> [SKIP][101] ([fdo#109280]) +4 similar issues
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-spr-indfb-draw-mmap-wc.html

  * igt@kms_hdr@bpc-switch-suspend@bpc-switch-suspend-edp-1-pipe-a:
    - shard-skl:          [PASS][102] -> [FAIL][103] ([i915#1188])
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-skl6/igt@kms_hdr@bpc-switch-suspend@bpc-switch-suspend-edp-1-pipe-a.html
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl1/igt@kms_hdr@bpc-switch-suspend@bpc-switch-suspend-edp-1-pipe-a.html

  * igt@kms_plane_alpha_blend@pipe-b-coverage-7efc:
    - shard-skl:          [PASS][104] -> [FAIL][105] ([fdo#108145] / [i915#265])
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-skl8/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-skl7/igt@kms_plane_alpha_blend@pipe-b-coverage-7efc.html

  * igt@kms_plane_alpha_blend@pipe-c-alpha-7efc:
    - shard-kbl:          NOTRUN -> [FAIL][106] ([fdo#108145] / [i915#265])
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-kbl1/igt@kms_plane_alpha_blend@pipe-c-alpha-7efc.html
    - shard-apl:          NOTRUN -> [FAIL][107] ([fdo#108145] / [i915#265])
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-apl4/igt@kms_plane_alpha_blend@pipe-c-alpha-7efc.html

  * igt@kms_plane_multiple@atomic-pipe-d-tiling-4:
    - shard-apl:          NOTRUN -> [SKIP][108] ([fdo#109271]) +17 similar issues
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-apl4/igt@kms_plane_multiple@atomic-pipe-d-tiling-4.html

  * igt@kms_plane_scaling@downscale-with-pixel-format-factor-0-25@pipe-a-edp-1-downscale-with-pixel-format:
    - shard-iclb:         NOTRUN -> [SKIP][109] ([i915#5176]) +2 similar issues
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@kms_plane_scaling@downscale-with-pixel-format-factor-0-25@pipe-a-edp-1-downscale-with-pixel-format.html

  * igt@kms_psr@psr2_cursor_plane_move:
    - shard-iclb:         [PASS][110] -> [SKIP][111] ([fdo#109441])
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-iclb2/igt@kms_psr@psr2_cursor_plane_move.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb8/igt@kms_psr@psr2_cursor_plane_move.html

  * igt@nouveau_crc@pipe-a-source-outp-complete:
    - shard-tglb:         NOTRUN -> [SKIP][112] ([i915#2530])
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb3/igt@nouveau_crc@pipe-a-source-outp-complete.html
    - shard-iclb:         NOTRUN -> [SKIP][113] ([i915#2530])
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@nouveau_crc@pipe-a-source-outp-complete.html

  
#### Possible fixes ####

  * igt@fbdev@unaligned-write:
    - {shard-rkl}:        [SKIP][114] ([i915#2582]) -> [PASS][115]
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@fbdev@unaligned-write.html
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@fbdev@unaligned-write.html

  * igt@gem_eio@unwedge-stress:
    - {shard-tglu}:       [TIMEOUT][116] ([i915#3063] / [i915#3648]) -> [PASS][117]
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-tglu-1/igt@gem_eio@unwedge-stress.html
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglu-3/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_balancer@parallel-balancer:
    - shard-iclb:         [SKIP][118] ([i915#4525]) -> [PASS][119]
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-iclb7/igt@gem_exec_balancer@parallel-balancer.html
   [119]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb4/igt@gem_exec_balancer@parallel-balancer.html

  * igt@gem_exec_endless@dispatch@vecs0:
    - shard-tglb:         [INCOMPLETE][120] ([i915#3778]) -> [PASS][121]
   [120]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-tglb3/igt@gem_exec_endless@dispatch@vecs0.html
   [121]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb6/igt@gem_exec_endless@dispatch@vecs0.html

  * igt@gem_exec_fair@basic-none-solo@rcs0:
    - {shard-rkl}:        [FAIL][122] ([i915#2842]) -> [PASS][123]
   [122]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@gem_exec_fair@basic-none-solo@rcs0.html
   [123]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@gem_exec_fair@basic-none-solo@rcs0.html

  * igt@gem_exec_fair@basic-pace-share@rcs0:
    - shard-tglb:         [FAIL][124] ([i915#2842]) -> [PASS][125]
   [124]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-tglb8/igt@gem_exec_fair@basic-pace-share@rcs0.html
   [125]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglb6/igt@gem_exec_fair@basic-pace-share@rcs0.html

  * igt@gem_exec_fair@basic-pace@vecs0:
    - shard-iclb:         [FAIL][126] ([i915#2842]) -> [PASS][127] +1 similar issue
   [126]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-iclb5/igt@gem_exec_fair@basic-pace@vecs0.html
   [127]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb8/igt@gem_exec_fair@basic-pace@vecs0.html

  * igt@gem_exec_flush@basic-batch-kernel-default-uc:
    - shard-snb:          [SKIP][128] ([fdo#109271]) -> [PASS][129] +4 similar issues
   [128]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-snb6/igt@gem_exec_flush@basic-batch-kernel-default-uc.html
   [129]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-snb4/igt@gem_exec_flush@basic-batch-kernel-default-uc.html

  * igt@gem_exec_suspend@basic-s3-devices@smem:
    - shard-kbl:          [DMESG-WARN][130] -> [PASS][131]
   [130]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-kbl6/igt@gem_exec_suspend@basic-s3-devices@smem.html
   [131]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-kbl3/igt@gem_exec_suspend@basic-s3-devices@smem.html

  * igt@gem_exec_whisper@basic-queues-all:
    - shard-glk:          [DMESG-WARN][132] ([i915#118]) -> [PASS][133] +1 similar issue
   [132]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk5/igt@gem_exec_whisper@basic-queues-all.html
   [133]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk6/igt@gem_exec_whisper@basic-queues-all.html

  * igt@gem_exec_whisper@basic-queues-priority:
    - {shard-rkl}:        [INCOMPLETE][134] -> [PASS][135]
   [134]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@gem_exec_whisper@basic-queues-priority.html
   [135]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-4/igt@gem_exec_whisper@basic-queues-priority.html

  * igt@gem_mmap_gtt@close-race:
    - {shard-rkl}:        [INCOMPLETE][136] ([i915#5080]) -> [PASS][137]
   [136]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@gem_mmap_gtt@close-race.html
   [137]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-2/igt@gem_mmap_gtt@close-race.html

  * igt@gem_mmap_wc@set-cache-level:
    - {shard-rkl}:        [SKIP][138] ([i915#1850]) -> [PASS][139]
   [138]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@gem_mmap_wc@set-cache-level.html
   [139]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@gem_mmap_wc@set-cache-level.html

  * igt@gem_ppgtt@blt-vs-render-ctxn:
    - shard-snb:          [DMESG-FAIL][140] ([i915#3692]) -> [PASS][141]
   [140]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-snb6/igt@gem_ppgtt@blt-vs-render-ctxn.html
   [141]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-snb4/igt@gem_ppgtt@blt-vs-render-ctxn.html

  * igt@gem_softpin@allocator-evict-all-engines:
    - shard-glk:          [FAIL][142] ([i915#4171]) -> [PASS][143]
   [142]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk3/igt@gem_softpin@allocator-evict-all-engines.html
   [143]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk9/igt@gem_softpin@allocator-evict-all-engines.html

  * igt@i915_pm_dc@dc6-psr:
    - {shard-rkl}:        [SKIP][144] ([i915#658]) -> [PASS][145]
   [144]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@i915_pm_dc@dc6-psr.html
   [145]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@i915_pm_dc@dc6-psr.html

  * igt@i915_pm_dc@dc9-dpms:
    - {shard-tglu}:       [SKIP][146] ([i915#4281]) -> [PASS][147]
   [146]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-tglu-3/igt@i915_pm_dc@dc9-dpms.html
   [147]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-tglu-2/igt@i915_pm_dc@dc9-dpms.html

  * igt@i915_pm_rpm@gem-mmap-type@uc:
    - {shard-rkl}:        [SKIP][148] ([fdo#109308]) -> [PASS][149] +4 similar issues
   [148]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@i915_pm_rpm@gem-mmap-type@uc.html
   [149]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@i915_pm_rpm@gem-mmap-type@uc.html

  * igt@i915_pm_rpm@modeset-lpsp:
    - {shard-rkl}:        [SKIP][150] ([i915#1397]) -> [PASS][151]
   [150]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@i915_pm_rpm@modeset-lpsp.html
   [151]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@i915_pm_rpm@modeset-lpsp.html

  * igt@i915_pm_rpm@system-suspend-execbuf:
    - shard-iclb:         [INCOMPLETE][152] ([i915#5096]) -> [PASS][153]
   [152]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-iclb4/igt@i915_pm_rpm@system-suspend-execbuf.html
   [153]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb6/igt@i915_pm_rpm@system-suspend-execbuf.html

  * igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc:
    - {shard-rkl}:        [SKIP][154] ([i915#1845] / [i915#4098]) -> [PASS][155] +20 similar issues
   [154]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc.html
   [155]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@kms_ccs@pipe-b-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_ccs:
    - shard-kbl:          [DMESG-WARN][156] ([i915#62] / [i915#92]) -> [PASS][157] +5 similar issues
   [156]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-kbl6/igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_ccs.html
   [157]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-kbl3/igt@kms_ccs@pipe-b-crc-sprite-planes-basic-y_tiled_ccs.html

  * igt@kms_color@pipe-b-degamma:
    - {shard-rkl}:        [SKIP][158] ([i915#1149] / [i915#1849] / [i915#4070] / [i915#4098]) -> [PASS][159] +1 similar issue
   [158]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@kms_color@pipe-b-degamma.html
   [159]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@kms_color@pipe-b-degamma.html

  * igt@kms_color@pipe-c-invalid-degamma-lut-sizes:
    - {shard-rkl}:        [SKIP][160] ([i915#4070]) -> [PASS][161] +2 similar issues
   [160]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-6/igt@kms_color@pipe-c-invalid-degamma-lut-sizes.html
   [161]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-5/igt@kms_color@pipe-c-invalid-degamma-lut-sizes.html

  * igt@kms_cursor_crc@pipe-b-cursor-64x21-random:
    - {shard-rkl}:        [SKIP][162] ([fdo#112022] / [i915#4070]) -> [PASS][163] +6 similar issues
   [162]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@kms_cursor_crc@pipe-b-cursor-64x21-random.html
   [163]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@kms_cursor_crc@pipe-b-cursor-64x21-random.html

  * igt@kms_cursor_edge_walk@pipe-b-256x256-right-edge:
    - {shard-rkl}:        [SKIP][164] ([i915#1849] / [i915#4070] / [i915#4098]) -> [PASS][165] +2 similar issues
   [164]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@kms_cursor_edge_walk@pipe-b-256x256-right-edge.html
   [165]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@kms_cursor_edge_walk@pipe-b-256x256-right-edge.html

  * igt@kms_cursor_legacy@cursor-vs-flip-legacy:
    - {shard-rkl}:        [SKIP][166] ([fdo#111825] / [i915#4070]) -> [PASS][167] +1 similar issue
   [166]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-rkl-5/igt@kms_cursor_legacy@cursor-vs-flip-legacy.html
   [167]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-rkl-6/igt@kms_cursor_legacy@cursor-vs-flip-legacy.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-glk:          [FAIL][168] ([i915#2346] / [i915#533]) -> [PASS][169]
   [168]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-glk4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [169]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-glk5/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_cursor_legacy@flip-vs-cursor-toggle:
    - shard-iclb:         [FAIL][170] ([i915#2346]) -> [PASS][171]
   [170]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11467/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor-toggle.html
   [171]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/shard-iclb4/igt@kms_cursor_legacy@flip-vs-cursor-toggle.h

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_22801/index.html

[-- Attachment #2: Type: text/html, Size: 33390 bytes --]

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version Ville Syrjala
@ 2022-04-07 10:10   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 10:10 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We have the BDB version cached, use it. We're going to have to
> start doing some of the BDB block parsing later, at which point
> we may no longer have the VBT around anymore (we free it at the
> end of intel_bios_init() when it didn't come via OpRegion).
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 54 +++++++++++------------
>  1 file changed, 27 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 556169ce0544..5518f4cfa1b1 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -415,7 +415,7 @@ parse_panel_dtd(struct drm_i915_private *i915,
>  	 * try the new generic DTD block first on VBT >= 229, but still fall
>  	 * back to trying the old LFP block if that fails.
>  	 */
> -	if (bdb->version >= 229)
> +	if (i915->vbt.version >= 229)
>  		parse_generic_dtd(i915, bdb);
>  	if (!i915->vbt.lfp_lvds_vbt_mode)
>  		parse_lfp_panel_dtd(i915, bdb);
> @@ -452,12 +452,12 @@ parse_lfp_backlight(struct drm_i915_private *i915,
>  	}
>  
>  	i915->vbt.backlight.type = INTEL_BACKLIGHT_DISPLAY_DDI;
> -	if (bdb->version >= 191) {
> +	if (i915->vbt.version >= 191) {
>  		size_t exp_size;
>  
> -		if (bdb->version >= 236)
> +		if (i915->vbt.version >= 236)
>  			exp_size = sizeof(struct bdb_lfp_backlight_data);
> -		else if (bdb->version >= 234)
> +		else if (i915->vbt.version >= 234)
>  			exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_234;
>  		else
>  			exp_size = EXP_BDB_LFP_BL_DATA_SIZE_REV_191;
> @@ -474,14 +474,14 @@ parse_lfp_backlight(struct drm_i915_private *i915,
>  	i915->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz;
>  	i915->vbt.backlight.active_low_pwm = entry->active_low_pwm;
>  
> -	if (bdb->version >= 234) {
> +	if (i915->vbt.version >= 234) {
>  		u16 min_level;
>  		bool scale;
>  
>  		level = backlight_data->brightness_level[panel_type].level;
>  		min_level = backlight_data->brightness_min_level[panel_type].level;
>  
> -		if (bdb->version >= 236)
> +		if (i915->vbt.version >= 236)
>  			scale = backlight_data->brightness_precision_bits[panel_type] == 16;
>  		else
>  			scale = level > 255;
> @@ -581,7 +581,7 @@ parse_general_features(struct drm_i915_private *i915,
>  
>  	i915->vbt.int_tv_support = general->int_tv_support;
>  	/* int_crt_support can't be trusted on earlier platforms */
> -	if (bdb->version >= 155 &&
> +	if (i915->vbt.version >= 155 &&
>  	    (HAS_DDI(i915) || IS_VALLEYVIEW(i915)))
>  		i915->vbt.int_crt_support = general->int_crt_support;
>  	i915->vbt.lvds_use_ssc = general->enable_ssc;
> @@ -589,7 +589,7 @@ parse_general_features(struct drm_i915_private *i915,
>  		intel_bios_ssc_frequency(i915, general->ssc_freq);
>  	i915->vbt.display_clock_mode = general->display_clock_mode;
>  	i915->vbt.fdi_rx_polarity_inverted = general->fdi_rx_polarity_inverted;
> -	if (bdb->version >= 181) {
> +	if (i915->vbt.version >= 181) {
>  		i915->vbt.orientation = general->rotate_180 ?
>  			DRM_MODE_PANEL_ORIENTATION_BOTTOM_UP :
>  			DRM_MODE_PANEL_ORIENTATION_NORMAL;
> @@ -597,7 +597,7 @@ parse_general_features(struct drm_i915_private *i915,
>  		i915->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
>  	}
>  
> -	if (bdb->version >= 249 && general->afc_startup_config) {
> +	if (i915->vbt.version >= 249 && general->afc_startup_config) {
>  		i915->vbt.override_afc_startup = true;
>  		i915->vbt.override_afc_startup_val = general->afc_startup_config == 0x1 ? 0x0 : 0x7;
>  	}
> @@ -724,13 +724,13 @@ parse_driver_features(struct drm_i915_private *i915,
>  		 * in the wild with the bits correctly populated. Version
>  		 * 108 (on i85x) does not have the bits correctly populated.
>  		 */
> -		if (bdb->version >= 134 &&
> +		if (i915->vbt.version >= 134 &&
>  		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_LVDS &&
>  		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
>  			i915->vbt.int_lvds_support = 0;
>  	}
>  
> -	if (bdb->version < 228) {
> +	if (i915->vbt.version < 228) {
>  		drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
>  			    driver->drrs_enabled);
>  		/*
> @@ -753,7 +753,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
>  	const struct bdb_lfp_power *power;
>  	u8 panel_type = i915->vbt.panel_type;
>  
> -	if (bdb->version < 228)
> +	if (i915->vbt.version < 228)
>  		return;
>  
>  	power = find_section(bdb, BDB_LFP_POWER);
> @@ -771,7 +771,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
>  	if (!(power->drrs & BIT(panel_type)))
>  		i915->vbt.drrs_type = DRRS_TYPE_NONE;
>  
> -	if (bdb->version >= 232)
> +	if (i915->vbt.version >= 232)
>  		i915->vbt.edp.hobl = power->hobl & BIT(panel_type);
>  }
>  
> @@ -876,7 +876,7 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
>  		break;
>  	}
>  
> -	if (bdb->version >= 173) {
> +	if (i915->vbt.version >= 173) {
>  		u8 vswing;
>  
>  		/* Don't read from VBT if module parameter has valid value*/
> @@ -919,7 +919,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
>  	 * New psr options 0=500us, 1=100us, 2=2500us, 3=0us
>  	 * Old decimal value is wake up time in multiples of 100 us.
>  	 */
> -	if (bdb->version >= 205 &&
> +	if (i915->vbt.version >= 205 &&
>  	    (DISPLAY_VER(i915) >= 9 && !IS_BROXTON(i915))) {
>  		switch (psr_table->tp1_wakeup_time) {
>  		case 0:
> @@ -965,7 +965,7 @@ parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
>  		i915->vbt.psr.tp2_tp3_wakeup_time_us = psr_table->tp2_tp3_wakeup_time * 100;
>  	}
>  
> -	if (bdb->version >= 226) {
> +	if (i915->vbt.version >= 226) {
>  		u32 wakeup_time = psr->psr2_tp2_tp3_wakeup_time;
>  
>  		wakeup_time = (wakeup_time >> (2 * panel_type)) & 0x3;
> @@ -1085,7 +1085,7 @@ parse_mipi_config(struct drm_i915_private *i915,
>  		return;
>  	}
>  
> -	parse_dsi_backlight_ports(i915, bdb->version, port);
> +	parse_dsi_backlight_ports(i915, i915->vbt.version, port);
>  
>  	/* FIXME is the 90 vs. 270 correct? */
>  	switch (config->rotation) {
> @@ -1448,7 +1448,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
>  	u16 block_size;
>  	int index;
>  
> -	if (bdb->version < 198)
> +	if (i915->vbt.version < 198)
>  		return;
>  
>  	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
> @@ -2117,31 +2117,31 @@ parse_general_definitions(struct drm_i915_private *i915,
>  	if (intel_gmbus_is_valid_pin(i915, bus_pin))
>  		i915->vbt.crt_ddc_pin = bus_pin;
>  
> -	if (bdb->version < 106) {
> +	if (i915->vbt.version < 106) {
>  		expected_size = 22;
> -	} else if (bdb->version < 111) {
> +	} else if (i915->vbt.version < 111) {
>  		expected_size = 27;
> -	} else if (bdb->version < 195) {
> +	} else if (i915->vbt.version < 195) {
>  		expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE;
> -	} else if (bdb->version == 195) {
> +	} else if (i915->vbt.version == 195) {
>  		expected_size = 37;
> -	} else if (bdb->version <= 215) {
> +	} else if (i915->vbt.version <= 215) {
>  		expected_size = 38;
> -	} else if (bdb->version <= 237) {
> +	} else if (i915->vbt.version <= 237) {
>  		expected_size = 39;
>  	} else {
>  		expected_size = sizeof(*child);
>  		BUILD_BUG_ON(sizeof(*child) < 39);
>  		drm_dbg(&i915->drm,
>  			"Expected child device config size for VBT version %u not known; assuming %u\n",
> -			bdb->version, expected_size);
> +			i915->vbt.version, expected_size);
>  	}
>  
>  	/* Flag an error for unexpected size, but continue anyway. */
>  	if (defs->child_dev_size != expected_size)
>  		drm_err(&i915->drm,
>  			"Unexpected child device config size %u (expected %u for VBT version %u)\n",
> -			defs->child_dev_size, expected_size, bdb->version);
> +			defs->child_dev_size, expected_size, i915->vbt.version);
>  
>  	/* The legacy sized child device config is the minimum we need. */
>  	if (defs->child_dev_size < LEGACY_CHILD_DEVICE_CONFIG_SIZE) {
> @@ -2497,7 +2497,7 @@ void intel_bios_init(struct drm_i915_private *i915)
>  
>  	drm_dbg_kms(&i915->drm,
>  		    "VBT signature \"%.*s\", BDB version %d\n",
> -		    (int)sizeof(vbt->signature), vbt->signature, bdb->version);
> +		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
>  
>  	/* Grab useful general definitions */
>  	parse_general_features(i915, bdb);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 02/22] drm/i915/bios: Make copies of VBT data blocks
  2022-04-06 13:38   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
@ 2022-04-07 10:23     ` Jani Nikula
  2022-04-07 11:18       ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 10:23 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make a copy of each VB data block with a guaranteed minimum
> size. The extra (if any) will just be left zeroed.
>
> This means we don't have to worry about going out of bounds
> when accessing any of the structure members. Otherwise that
> could easliy happen if we simply get the version check wrong,
> or if the VBT is broken/malicious.
>
> v2: Don't do arithmetic between bdb header and copy
>     of the LFP data block (Jani)
> v3: Make all the copies up front
> v4: Only WARN about min_size==0 if we found the block
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 230 ++++++++++++++++------
>  drivers/gpu/drm/i915/i915_drv.h           |   1 +
>  2 files changed, 174 insertions(+), 57 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 5518f4cfa1b1..068978734e3b 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
>  }
>  
>  static const void *
> -find_section(const void *_bdb, enum bdb_block_id section_id)
> +find_raw_section(const void *_bdb, enum bdb_block_id section_id)
>  {
>  	const struct bdb_header *bdb = _bdb;
>  	const u8 *base = _bdb;
> @@ -118,6 +118,124 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
>  	return NULL;
>  }
>  
> +/*
> + * Offset from the start of BDB to the start of the
> + * block data (just past the block header).
> + */
> +static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
> +{
> +	const void *block;
> +
> +	block = find_raw_section(bdb, section_id);
> +	if (!block)
> +		return 0;
> +
> +	return block - bdb;
> +}
> +
> +struct bdb_block_entry {
> +	struct list_head node;
> +	enum bdb_block_id section_id;
> +	u8 data[];
> +};
> +
> +static const void *
> +find_section(struct drm_i915_private *i915,
> +	     enum bdb_block_id section_id)
> +{
> +	struct bdb_block_entry *entry;
> +
> +	list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
> +		if (entry->section_id == section_id)
> +			return entry->data + 3;
> +	}
> +

Failing to find the section_id in the list above, perhaps this should
check if the section_id is present in bdb_blocks[] and complain
loudly. If we fail to add a section there, this will never find
it. I.e. we should never call find_section() on a section_id that isn't
present in bdb_blocks[].

I also dislike the +/- 3 here and there.

But both of these can be cleaned up later.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +	return NULL;
> +}
> +
> +static const struct {
> +	enum bdb_block_id section_id;
> +	size_t min_size;
> +} bdb_blocks[] = {
> +	{ .section_id = BDB_GENERAL_FEATURES,
> +	  .min_size = sizeof(struct bdb_general_features), },
> +	{ .section_id = BDB_GENERAL_DEFINITIONS,
> +	  .min_size = sizeof(struct bdb_general_definitions), },
> +	{ .section_id = BDB_PSR,
> +	  .min_size = sizeof(struct bdb_psr), },
> +	{ .section_id = BDB_DRIVER_FEATURES,
> +	  .min_size = sizeof(struct bdb_driver_features), },
> +	{ .section_id = BDB_SDVO_LVDS_OPTIONS,
> +	  .min_size = sizeof(struct bdb_sdvo_lvds_options), },
> +	{ .section_id = BDB_SDVO_PANEL_DTDS,
> +	  .min_size = sizeof(struct bdb_sdvo_panel_dtds), },
> +	{ .section_id = BDB_EDP,
> +	  .min_size = sizeof(struct bdb_edp), },
> +	{ .section_id = BDB_LVDS_OPTIONS,
> +	  .min_size = sizeof(struct bdb_lvds_options), },
> +	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
> +	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
> +	{ .section_id = BDB_LVDS_LFP_DATA,
> +	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
> +	{ .section_id = BDB_LVDS_BACKLIGHT,
> +	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
> +	{ .section_id = BDB_LFP_POWER,
> +	  .min_size = sizeof(struct bdb_lfp_power), },
> +	{ .section_id = BDB_MIPI_CONFIG,
> +	  .min_size = sizeof(struct bdb_mipi_config), },
> +	{ .section_id = BDB_MIPI_SEQUENCE,
> +	  .min_size = sizeof(struct bdb_mipi_sequence) },
> +	{ .section_id = BDB_COMPRESSION_PARAMETERS,
> +	  .min_size = sizeof(struct bdb_compression_parameters), },
> +	{ .section_id = BDB_GENERIC_DTD,
> +	  .min_size = sizeof(struct bdb_generic_dtd), },
> +};
> +
> +static void
> +init_bdb_block(struct drm_i915_private *i915,
> +	       const void *bdb, enum bdb_block_id section_id,
> +	       size_t min_size)
> +{
> +	struct bdb_block_entry *entry;
> +	const void *block;
> +	size_t block_size;
> +
> +	block = find_raw_section(bdb, section_id);
> +	if (!block)
> +		return;
> +
> +	drm_WARN(&i915->drm, min_size == 0,
> +		 "Block %d min_size is zero\n", section_id);
> +
> +	block_size = get_blocksize(block);
> +
> +	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
> +			GFP_KERNEL);
> +	if (!entry)
> +		return;
> +
> +	entry->section_id = section_id;
> +	memcpy(entry->data, block - 3, block_size + 3);
> +
> +	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
> +		    section_id, block_size, min_size);
> +
> +	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
> +}
> +
> +static void init_bdb_blocks(struct drm_i915_private *i915,
> +			    const void *bdb)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
> +		enum bdb_block_id section_id = bdb_blocks[i].section_id;
> +		size_t min_size = bdb_blocks[i].min_size;
> +
> +		init_bdb_block(i915, bdb, section_id, min_size);
> +	}
> +}
> +
>  static void
>  fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
>  			const struct lvds_dvo_timing *dvo_timing)
> @@ -199,7 +317,7 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
>  		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
>  		   int index)
>  {
> -	size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
> +	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
>  	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
>  	size_t ofs;
>  
> @@ -214,15 +332,14 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
>  
>  /* Parse general panel options */
>  static void
> -parse_panel_options(struct drm_i915_private *i915,
> -		    const struct bdb_header *bdb)
> +parse_panel_options(struct drm_i915_private *i915)
>  {
>  	const struct bdb_lvds_options *lvds_options;
>  	int panel_type;
>  	int drrs_mode;
>  	int ret;
>  
> -	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
> +	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
>  	if (!lvds_options)
>  		return;
>  
> @@ -285,11 +402,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
>  	struct drm_display_mode *panel_fixed_mode;
>  	int panel_type = i915->vbt.panel_type;
>  
> -	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
> +	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
>  	if (!lvds_lfp_data)
>  		return;
>  
> -	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
> +	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
>  	if (!lvds_lfp_data_ptrs)
>  		return;
>  
> @@ -325,15 +442,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
>  }
>  
>  static void
> -parse_generic_dtd(struct drm_i915_private *i915,
> -		  const struct bdb_header *bdb)
> +parse_generic_dtd(struct drm_i915_private *i915)
>  {
>  	const struct bdb_generic_dtd *generic_dtd;
>  	const struct generic_dtd_entry *dtd;
>  	struct drm_display_mode *panel_fixed_mode;
>  	int num_dtd;
>  
> -	generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
> +	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
>  	if (!generic_dtd)
>  		return;
>  
> @@ -416,21 +532,20 @@ parse_panel_dtd(struct drm_i915_private *i915,
>  	 * back to trying the old LFP block if that fails.
>  	 */
>  	if (i915->vbt.version >= 229)
> -		parse_generic_dtd(i915, bdb);
> +		parse_generic_dtd(i915);
>  	if (!i915->vbt.lfp_lvds_vbt_mode)
>  		parse_lfp_panel_dtd(i915, bdb);
>  }
>  
>  static void
> -parse_lfp_backlight(struct drm_i915_private *i915,
> -		    const struct bdb_header *bdb)
> +parse_lfp_backlight(struct drm_i915_private *i915)
>  {
>  	const struct bdb_lfp_backlight_data *backlight_data;
>  	const struct lfp_backlight_data_entry *entry;
>  	int panel_type = i915->vbt.panel_type;
>  	u16 level;
>  
> -	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
> +	backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
>  	if (!backlight_data)
>  		return;
>  
> @@ -514,8 +629,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
>  
>  /* Try to find sdvo panel data */
>  static void
> -parse_sdvo_panel_data(struct drm_i915_private *i915,
> -		      const struct bdb_header *bdb)
> +parse_sdvo_panel_data(struct drm_i915_private *i915)
>  {
>  	const struct bdb_sdvo_panel_dtds *dtds;
>  	struct drm_display_mode *panel_fixed_mode;
> @@ -531,14 +645,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
>  	if (index == -1) {
>  		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
>  
> -		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
> +		sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
>  		if (!sdvo_lvds_options)
>  			return;
>  
>  		index = sdvo_lvds_options->panel_type;
>  	}
>  
> -	dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
> +	dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
>  	if (!dtds)
>  		return;
>  
> @@ -570,12 +684,11 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
>  }
>  
>  static void
> -parse_general_features(struct drm_i915_private *i915,
> -		       const struct bdb_header *bdb)
> +parse_general_features(struct drm_i915_private *i915)
>  {
>  	const struct bdb_general_features *general;
>  
> -	general = find_section(bdb, BDB_GENERAL_FEATURES);
> +	general = find_section(i915, BDB_GENERAL_FEATURES);
>  	if (!general)
>  		return;
>  
> @@ -695,12 +808,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
>  }
>  
>  static void
> -parse_driver_features(struct drm_i915_private *i915,
> -		      const struct bdb_header *bdb)
> +parse_driver_features(struct drm_i915_private *i915)
>  {
>  	const struct bdb_driver_features *driver;
>  
> -	driver = find_section(bdb, BDB_DRIVER_FEATURES);
> +	driver = find_section(i915, BDB_DRIVER_FEATURES);
>  	if (!driver)
>  		return;
>  
> @@ -747,8 +859,7 @@ parse_driver_features(struct drm_i915_private *i915,
>  }
>  
>  static void
> -parse_power_conservation_features(struct drm_i915_private *i915,
> -				  const struct bdb_header *bdb)
> +parse_power_conservation_features(struct drm_i915_private *i915)
>  {
>  	const struct bdb_lfp_power *power;
>  	u8 panel_type = i915->vbt.panel_type;
> @@ -756,7 +867,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
>  	if (i915->vbt.version < 228)
>  		return;
>  
> -	power = find_section(bdb, BDB_LFP_POWER);
> +	power = find_section(i915, BDB_LFP_POWER);
>  	if (!power)
>  		return;
>  
> @@ -776,14 +887,14 @@ parse_power_conservation_features(struct drm_i915_private *i915,
>  }
>  
>  static void
> -parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
> +parse_edp(struct drm_i915_private *i915)
>  {
>  	const struct bdb_edp *edp;
>  	const struct edp_power_seq *edp_pps;
>  	const struct edp_fast_link_params *edp_link_params;
>  	int panel_type = i915->vbt.panel_type;
>  
> -	edp = find_section(bdb, BDB_EDP);
> +	edp = find_section(i915, BDB_EDP);
>  	if (!edp)
>  		return;
>  
> @@ -894,13 +1005,13 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
>  }
>  
>  static void
> -parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
> +parse_psr(struct drm_i915_private *i915)
>  {
>  	const struct bdb_psr *psr;
>  	const struct psr_table *psr_table;
>  	int panel_type = i915->vbt.panel_type;
>  
> -	psr = find_section(bdb, BDB_PSR);
> +	psr = find_section(i915, BDB_PSR);
>  	if (!psr) {
>  		drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
>  		return;
> @@ -1034,8 +1145,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
>  }
>  
>  static void
> -parse_mipi_config(struct drm_i915_private *i915,
> -		  const struct bdb_header *bdb)
> +parse_mipi_config(struct drm_i915_private *i915)
>  {
>  	const struct bdb_mipi_config *start;
>  	const struct mipi_config *config;
> @@ -1058,7 +1168,7 @@ parse_mipi_config(struct drm_i915_private *i915,
>  	/* Parse #52 for panel index used from panel_type already
>  	 * parsed
>  	 */
> -	start = find_section(bdb, BDB_MIPI_CONFIG);
> +	start = find_section(i915, BDB_MIPI_CONFIG);
>  	if (!start) {
>  		drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
>  		return;
> @@ -1354,8 +1464,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
>  }
>  
>  static void
> -parse_mipi_sequence(struct drm_i915_private *i915,
> -		    const struct bdb_header *bdb)
> +parse_mipi_sequence(struct drm_i915_private *i915)
>  {
>  	int panel_type = i915->vbt.panel_type;
>  	const struct bdb_mipi_sequence *sequence;
> @@ -1368,7 +1477,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
>  	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
>  		return;
>  
> -	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
> +	sequence = find_section(i915, BDB_MIPI_SEQUENCE);
>  	if (!sequence) {
>  		drm_dbg_kms(&i915->drm,
>  			    "No MIPI Sequence found, parsing complete\n");
> @@ -1439,8 +1548,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
>  }
>  
>  static void
> -parse_compression_parameters(struct drm_i915_private *i915,
> -			     const struct bdb_header *bdb)
> +parse_compression_parameters(struct drm_i915_private *i915)
>  {
>  	const struct bdb_compression_parameters *params;
>  	struct intel_bios_encoder_data *devdata;
> @@ -1451,7 +1559,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
>  	if (i915->vbt.version < 198)
>  		return;
>  
> -	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
> +	params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
>  	if (params) {
>  		/* Sanity checks */
>  		if (params->entry_size != sizeof(params->data[0])) {
> @@ -2086,8 +2194,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
>  }
>  
>  static void
> -parse_general_definitions(struct drm_i915_private *i915,
> -			  const struct bdb_header *bdb)
> +parse_general_definitions(struct drm_i915_private *i915)
>  {
>  	const struct bdb_general_definitions *defs;
>  	struct intel_bios_encoder_data *devdata;
> @@ -2097,7 +2204,7 @@ parse_general_definitions(struct drm_i915_private *i915,
>  	u16 block_size;
>  	int bus_pin;
>  
> -	defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
> +	defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
>  	if (!defs) {
>  		drm_dbg_kms(&i915->drm,
>  			    "No general definition block is found, no devices defined.\n");
> @@ -2466,6 +2573,7 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	const struct bdb_header *bdb;
>  
>  	INIT_LIST_HEAD(&i915->vbt.display_devices);
> +	INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
>  
>  	if (!HAS_DISPLAY(i915)) {
>  		drm_dbg_kms(&i915->drm,
> @@ -2499,22 +2607,24 @@ void intel_bios_init(struct drm_i915_private *i915)
>  		    "VBT signature \"%.*s\", BDB version %d\n",
>  		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
>  
> +	init_bdb_blocks(i915, bdb);
> +
>  	/* Grab useful general definitions */
> -	parse_general_features(i915, bdb);
> -	parse_general_definitions(i915, bdb);
> -	parse_panel_options(i915, bdb);
> +	parse_general_features(i915);
> +	parse_general_definitions(i915);
> +	parse_panel_options(i915);
>  	parse_panel_dtd(i915, bdb);
> -	parse_lfp_backlight(i915, bdb);
> -	parse_sdvo_panel_data(i915, bdb);
> -	parse_driver_features(i915, bdb);
> -	parse_power_conservation_features(i915, bdb);
> -	parse_edp(i915, bdb);
> -	parse_psr(i915, bdb);
> -	parse_mipi_config(i915, bdb);
> -	parse_mipi_sequence(i915, bdb);
> +	parse_lfp_backlight(i915);
> +	parse_sdvo_panel_data(i915);
> +	parse_driver_features(i915);
> +	parse_power_conservation_features(i915);
> +	parse_edp(i915);
> +	parse_psr(i915);
> +	parse_mipi_config(i915);
> +	parse_mipi_sequence(i915);
>  
>  	/* Depends on child device list */
> -	parse_compression_parameters(i915, bdb);
> +	parse_compression_parameters(i915);
>  
>  out:
>  	if (!vbt) {
> @@ -2536,14 +2646,20 @@ void intel_bios_init(struct drm_i915_private *i915)
>   */
>  void intel_bios_driver_remove(struct drm_i915_private *i915)
>  {
> -	struct intel_bios_encoder_data *devdata, *n;
> +	struct intel_bios_encoder_data *devdata, *nd;
> +	struct bdb_block_entry *entry, *ne;
>  
> -	list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
> +	list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
>  		list_del(&devdata->node);
>  		kfree(devdata->dsc);
>  		kfree(devdata);
>  	}
>  
> +	list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
> +		list_del(&entry->node);
> +		kfree(entry);
> +	}
> +
>  	kfree(i915->vbt.sdvo_lvds_vbt_mode);
>  	i915->vbt.sdvo_lvds_vbt_mode = NULL;
>  	kfree(i915->vbt.lfp_lvds_vbt_mode);
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 06e7c2802c5e..9274417cd87a 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -380,6 +380,7 @@ struct intel_vbt_data {
>  	int crt_ddc_pin;
>  
>  	struct list_head display_devices;
> +	struct list_head bdb_blocks;
>  
>  	struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
>  	struct sdvo_device_mapping sdvo_mappings[2];

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 03/22] drm/i915/bios: Use the copy of the LFP data table always
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 03/22] drm/i915/bios: Use the copy of the LFP data table always Ville Syrjala
@ 2022-04-07 10:36   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 10:36 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Currently get_lvds_fp_timing() still returns a pointer to the original
> data block rather than our copy. Let's convert the data pointer offsets
> to be relative to the data block rather than the whole BDB. With that
> we can make get_lvds_fp_timing() return a pointer to the copy.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 41 +++++++++++++++++++----
>  1 file changed, 34 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 2e9f639d092e..000544280c35 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -191,6 +191,29 @@ static const struct {
>  	  .min_size = sizeof(struct bdb_generic_dtd), },
>  };
>  
> +/* make the data table offsets relative to the data block */
> +static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
> +{
> +	struct bdb_lvds_lfp_data_ptrs *ptrs = ptrs_block;
> +	u32 offset;
> +	int i;
> +
> +	offset = block_offset(bdb, BDB_LVDS_LFP_DATA);
> +
> +	for (i = 0; i < 16; i++) {
> +		if (ptrs->ptr[i].fp_timing.offset < offset ||
> +		    ptrs->ptr[i].dvo_timing.offset < offset ||
> +		    ptrs->ptr[i].panel_pnp_id.offset < offset)
> +			return false;
> +
> +		ptrs->ptr[i].fp_timing.offset -= offset;
> +		ptrs->ptr[i].dvo_timing.offset -= offset;
> +		ptrs->ptr[i].panel_pnp_id.offset -= offset;
> +	}
> +
> +	return true;
> +}
> +
>  static void
>  init_bdb_block(struct drm_i915_private *i915,
>  	       const void *bdb, enum bdb_block_id section_id,
> @@ -217,6 +240,13 @@ init_bdb_block(struct drm_i915_private *i915,
>  	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
>  		    section_id, block_size, min_size);
>  
> +	if (section_id == BDB_LVDS_LFP_DATA_PTRS &&
> +	    !fixup_lfp_data_ptrs(bdb, entry->data + 3)) {
> +		drm_err(&i915->drm, "VBT has malformed LFP data table pointers\n");
> +		kfree(entry);
> +		return;
> +	}
> +
>  	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
>  }
>  
> @@ -312,22 +342,19 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
>   * this function may return NULL if the corresponding entry is invalid
>   */
>  static const struct lvds_fp_timing *
> -get_lvds_fp_timing(const struct bdb_header *bdb,
> -		   const struct bdb_lvds_lfp_data *data,
> +get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
>  		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
>  		   int index)
>  {
> -	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
>  	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
>  	size_t ofs;
>  
>  	if (index >= ARRAY_SIZE(ptrs->ptr))
>  		return NULL;
>  	ofs = ptrs->ptr[index].fp_timing.offset;
> -	if (ofs < data_ofs ||
> -	    ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size)
> +	if (ofs + sizeof(struct lvds_fp_timing) > data_size)
>  		return NULL;
> -	return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs);
> +	return (const struct lvds_fp_timing *)((const u8 *)data + ofs);
>  }
>  
>  /* Parse general panel options */
> @@ -426,7 +453,7 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
>  		    "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n",
>  		    DRM_MODE_ARG(panel_fixed_mode));
>  
> -	fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data,
> +	fp_timing = get_lvds_fp_timing(lvds_lfp_data,
>  				       lvds_lfp_data_ptrs,
>  				       panel_type);
>  	if (fp_timing) {

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 02/22] drm/i915/bios: Make copies of VBT data blocks
  2022-04-07 10:23     ` Jani Nikula
@ 2022-04-07 11:18       ` Ville Syrjälä
  2022-04-07 12:06         ` Jani Nikula
  0 siblings, 1 reply; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-07 11:18 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 01:23:38PM +0300, Jani Nikula wrote:
> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Make a copy of each VB data block with a guaranteed minimum
> > size. The extra (if any) will just be left zeroed.
> >
> > This means we don't have to worry about going out of bounds
> > when accessing any of the structure members. Otherwise that
> > could easliy happen if we simply get the version check wrong,
> > or if the VBT is broken/malicious.
> >
> > v2: Don't do arithmetic between bdb header and copy
> >     of the LFP data block (Jani)
> > v3: Make all the copies up front
> > v4: Only WARN about min_size==0 if we found the block
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c | 230 ++++++++++++++++------
> >  drivers/gpu/drm/i915/i915_drv.h           |   1 +
> >  2 files changed, 174 insertions(+), 57 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 5518f4cfa1b1..068978734e3b 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
> >  }
> >  
> >  static const void *
> > -find_section(const void *_bdb, enum bdb_block_id section_id)
> > +find_raw_section(const void *_bdb, enum bdb_block_id section_id)
> >  {
> >  	const struct bdb_header *bdb = _bdb;
> >  	const u8 *base = _bdb;
> > @@ -118,6 +118,124 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
> >  	return NULL;
> >  }
> >  
> > +/*
> > + * Offset from the start of BDB to the start of the
> > + * block data (just past the block header).
> > + */
> > +static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
> > +{
> > +	const void *block;
> > +
> > +	block = find_raw_section(bdb, section_id);
> > +	if (!block)
> > +		return 0;
> > +
> > +	return block - bdb;
> > +}
> > +
> > +struct bdb_block_entry {
> > +	struct list_head node;
> > +	enum bdb_block_id section_id;
> > +	u8 data[];
> > +};
> > +
> > +static const void *
> > +find_section(struct drm_i915_private *i915,
> > +	     enum bdb_block_id section_id)
> > +{
> > +	struct bdb_block_entry *entry;
> > +
> > +	list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
> > +		if (entry->section_id == section_id)
> > +			return entry->data + 3;
> > +	}
> > +
> 
> Failing to find the section_id in the list above, perhaps this should
> check if the section_id is present in bdb_blocks[] and complain
> loudly. If we fail to add a section there, this will never find
> it. I.e. we should never call find_section() on a section_id that isn't
> present in bdb_blocks[].

That's perfectly legit. Eg. old VBTs are always missing a lot
of the eDP related blocks.

What we could do is add some kind of dummy block into the list
for every block we've initialized, whether we found it or not.
With that we could complain if find_section() gets called on
anything that we didn't try to duplicate.

> 
> I also dislike the +/- 3 here and there.

Yeah, I was pondering about defining a structure that actually includes
the BDB block header and try to replace all the magic +/-3 stuff with
that. But didn't feel like bloating this series any further right now.

> 
> But both of these can be cleaned up later.
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> 
> > +	return NULL;
> > +}
> > +
> > +static const struct {
> > +	enum bdb_block_id section_id;
> > +	size_t min_size;
> > +} bdb_blocks[] = {
> > +	{ .section_id = BDB_GENERAL_FEATURES,
> > +	  .min_size = sizeof(struct bdb_general_features), },
> > +	{ .section_id = BDB_GENERAL_DEFINITIONS,
> > +	  .min_size = sizeof(struct bdb_general_definitions), },
> > +	{ .section_id = BDB_PSR,
> > +	  .min_size = sizeof(struct bdb_psr), },
> > +	{ .section_id = BDB_DRIVER_FEATURES,
> > +	  .min_size = sizeof(struct bdb_driver_features), },
> > +	{ .section_id = BDB_SDVO_LVDS_OPTIONS,
> > +	  .min_size = sizeof(struct bdb_sdvo_lvds_options), },
> > +	{ .section_id = BDB_SDVO_PANEL_DTDS,
> > +	  .min_size = sizeof(struct bdb_sdvo_panel_dtds), },
> > +	{ .section_id = BDB_EDP,
> > +	  .min_size = sizeof(struct bdb_edp), },
> > +	{ .section_id = BDB_LVDS_OPTIONS,
> > +	  .min_size = sizeof(struct bdb_lvds_options), },
> > +	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
> > +	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
> > +	{ .section_id = BDB_LVDS_LFP_DATA,
> > +	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
> > +	{ .section_id = BDB_LVDS_BACKLIGHT,
> > +	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
> > +	{ .section_id = BDB_LFP_POWER,
> > +	  .min_size = sizeof(struct bdb_lfp_power), },
> > +	{ .section_id = BDB_MIPI_CONFIG,
> > +	  .min_size = sizeof(struct bdb_mipi_config), },
> > +	{ .section_id = BDB_MIPI_SEQUENCE,
> > +	  .min_size = sizeof(struct bdb_mipi_sequence) },
> > +	{ .section_id = BDB_COMPRESSION_PARAMETERS,
> > +	  .min_size = sizeof(struct bdb_compression_parameters), },
> > +	{ .section_id = BDB_GENERIC_DTD,
> > +	  .min_size = sizeof(struct bdb_generic_dtd), },
> > +};
> > +
> > +static void
> > +init_bdb_block(struct drm_i915_private *i915,
> > +	       const void *bdb, enum bdb_block_id section_id,
> > +	       size_t min_size)
> > +{
> > +	struct bdb_block_entry *entry;
> > +	const void *block;
> > +	size_t block_size;
> > +
> > +	block = find_raw_section(bdb, section_id);
> > +	if (!block)
> > +		return;
> > +
> > +	drm_WARN(&i915->drm, min_size == 0,
> > +		 "Block %d min_size is zero\n", section_id);
> > +
> > +	block_size = get_blocksize(block);
> > +
> > +	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
> > +			GFP_KERNEL);
> > +	if (!entry)
> > +		return;
> > +
> > +	entry->section_id = section_id;
> > +	memcpy(entry->data, block - 3, block_size + 3);
> > +
> > +	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
> > +		    section_id, block_size, min_size);
> > +
> > +	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
> > +}
> > +
> > +static void init_bdb_blocks(struct drm_i915_private *i915,
> > +			    const void *bdb)
> > +{
> > +	int i;
> > +
> > +	for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
> > +		enum bdb_block_id section_id = bdb_blocks[i].section_id;
> > +		size_t min_size = bdb_blocks[i].min_size;
> > +
> > +		init_bdb_block(i915, bdb, section_id, min_size);
> > +	}
> > +}
> > +
> >  static void
> >  fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
> >  			const struct lvds_dvo_timing *dvo_timing)
> > @@ -199,7 +317,7 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
> >  		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
> >  		   int index)
> >  {
> > -	size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
> > +	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
> >  	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
> >  	size_t ofs;
> >  
> > @@ -214,15 +332,14 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
> >  
> >  /* Parse general panel options */
> >  static void
> > -parse_panel_options(struct drm_i915_private *i915,
> > -		    const struct bdb_header *bdb)
> > +parse_panel_options(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_lvds_options *lvds_options;
> >  	int panel_type;
> >  	int drrs_mode;
> >  	int ret;
> >  
> > -	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
> > +	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
> >  	if (!lvds_options)
> >  		return;
> >  
> > @@ -285,11 +402,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
> >  	struct drm_display_mode *panel_fixed_mode;
> >  	int panel_type = i915->vbt.panel_type;
> >  
> > -	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
> > +	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
> >  	if (!lvds_lfp_data)
> >  		return;
> >  
> > -	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
> > +	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> >  	if (!lvds_lfp_data_ptrs)
> >  		return;
> >  
> > @@ -325,15 +442,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
> >  }
> >  
> >  static void
> > -parse_generic_dtd(struct drm_i915_private *i915,
> > -		  const struct bdb_header *bdb)
> > +parse_generic_dtd(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_generic_dtd *generic_dtd;
> >  	const struct generic_dtd_entry *dtd;
> >  	struct drm_display_mode *panel_fixed_mode;
> >  	int num_dtd;
> >  
> > -	generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
> > +	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
> >  	if (!generic_dtd)
> >  		return;
> >  
> > @@ -416,21 +532,20 @@ parse_panel_dtd(struct drm_i915_private *i915,
> >  	 * back to trying the old LFP block if that fails.
> >  	 */
> >  	if (i915->vbt.version >= 229)
> > -		parse_generic_dtd(i915, bdb);
> > +		parse_generic_dtd(i915);
> >  	if (!i915->vbt.lfp_lvds_vbt_mode)
> >  		parse_lfp_panel_dtd(i915, bdb);
> >  }
> >  
> >  static void
> > -parse_lfp_backlight(struct drm_i915_private *i915,
> > -		    const struct bdb_header *bdb)
> > +parse_lfp_backlight(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_lfp_backlight_data *backlight_data;
> >  	const struct lfp_backlight_data_entry *entry;
> >  	int panel_type = i915->vbt.panel_type;
> >  	u16 level;
> >  
> > -	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
> > +	backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
> >  	if (!backlight_data)
> >  		return;
> >  
> > @@ -514,8 +629,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
> >  
> >  /* Try to find sdvo panel data */
> >  static void
> > -parse_sdvo_panel_data(struct drm_i915_private *i915,
> > -		      const struct bdb_header *bdb)
> > +parse_sdvo_panel_data(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_sdvo_panel_dtds *dtds;
> >  	struct drm_display_mode *panel_fixed_mode;
> > @@ -531,14 +645,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
> >  	if (index == -1) {
> >  		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
> >  
> > -		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
> > +		sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
> >  		if (!sdvo_lvds_options)
> >  			return;
> >  
> >  		index = sdvo_lvds_options->panel_type;
> >  	}
> >  
> > -	dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
> > +	dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
> >  	if (!dtds)
> >  		return;
> >  
> > @@ -570,12 +684,11 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
> >  }
> >  
> >  static void
> > -parse_general_features(struct drm_i915_private *i915,
> > -		       const struct bdb_header *bdb)
> > +parse_general_features(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_general_features *general;
> >  
> > -	general = find_section(bdb, BDB_GENERAL_FEATURES);
> > +	general = find_section(i915, BDB_GENERAL_FEATURES);
> >  	if (!general)
> >  		return;
> >  
> > @@ -695,12 +808,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
> >  }
> >  
> >  static void
> > -parse_driver_features(struct drm_i915_private *i915,
> > -		      const struct bdb_header *bdb)
> > +parse_driver_features(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_driver_features *driver;
> >  
> > -	driver = find_section(bdb, BDB_DRIVER_FEATURES);
> > +	driver = find_section(i915, BDB_DRIVER_FEATURES);
> >  	if (!driver)
> >  		return;
> >  
> > @@ -747,8 +859,7 @@ parse_driver_features(struct drm_i915_private *i915,
> >  }
> >  
> >  static void
> > -parse_power_conservation_features(struct drm_i915_private *i915,
> > -				  const struct bdb_header *bdb)
> > +parse_power_conservation_features(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_lfp_power *power;
> >  	u8 panel_type = i915->vbt.panel_type;
> > @@ -756,7 +867,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
> >  	if (i915->vbt.version < 228)
> >  		return;
> >  
> > -	power = find_section(bdb, BDB_LFP_POWER);
> > +	power = find_section(i915, BDB_LFP_POWER);
> >  	if (!power)
> >  		return;
> >  
> > @@ -776,14 +887,14 @@ parse_power_conservation_features(struct drm_i915_private *i915,
> >  }
> >  
> >  static void
> > -parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
> > +parse_edp(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_edp *edp;
> >  	const struct edp_power_seq *edp_pps;
> >  	const struct edp_fast_link_params *edp_link_params;
> >  	int panel_type = i915->vbt.panel_type;
> >  
> > -	edp = find_section(bdb, BDB_EDP);
> > +	edp = find_section(i915, BDB_EDP);
> >  	if (!edp)
> >  		return;
> >  
> > @@ -894,13 +1005,13 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
> >  }
> >  
> >  static void
> > -parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
> > +parse_psr(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_psr *psr;
> >  	const struct psr_table *psr_table;
> >  	int panel_type = i915->vbt.panel_type;
> >  
> > -	psr = find_section(bdb, BDB_PSR);
> > +	psr = find_section(i915, BDB_PSR);
> >  	if (!psr) {
> >  		drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
> >  		return;
> > @@ -1034,8 +1145,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
> >  }
> >  
> >  static void
> > -parse_mipi_config(struct drm_i915_private *i915,
> > -		  const struct bdb_header *bdb)
> > +parse_mipi_config(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_mipi_config *start;
> >  	const struct mipi_config *config;
> > @@ -1058,7 +1168,7 @@ parse_mipi_config(struct drm_i915_private *i915,
> >  	/* Parse #52 for panel index used from panel_type already
> >  	 * parsed
> >  	 */
> > -	start = find_section(bdb, BDB_MIPI_CONFIG);
> > +	start = find_section(i915, BDB_MIPI_CONFIG);
> >  	if (!start) {
> >  		drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
> >  		return;
> > @@ -1354,8 +1464,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
> >  }
> >  
> >  static void
> > -parse_mipi_sequence(struct drm_i915_private *i915,
> > -		    const struct bdb_header *bdb)
> > +parse_mipi_sequence(struct drm_i915_private *i915)
> >  {
> >  	int panel_type = i915->vbt.panel_type;
> >  	const struct bdb_mipi_sequence *sequence;
> > @@ -1368,7 +1477,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
> >  	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
> >  		return;
> >  
> > -	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
> > +	sequence = find_section(i915, BDB_MIPI_SEQUENCE);
> >  	if (!sequence) {
> >  		drm_dbg_kms(&i915->drm,
> >  			    "No MIPI Sequence found, parsing complete\n");
> > @@ -1439,8 +1548,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
> >  }
> >  
> >  static void
> > -parse_compression_parameters(struct drm_i915_private *i915,
> > -			     const struct bdb_header *bdb)
> > +parse_compression_parameters(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_compression_parameters *params;
> >  	struct intel_bios_encoder_data *devdata;
> > @@ -1451,7 +1559,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
> >  	if (i915->vbt.version < 198)
> >  		return;
> >  
> > -	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
> > +	params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
> >  	if (params) {
> >  		/* Sanity checks */
> >  		if (params->entry_size != sizeof(params->data[0])) {
> > @@ -2086,8 +2194,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
> >  }
> >  
> >  static void
> > -parse_general_definitions(struct drm_i915_private *i915,
> > -			  const struct bdb_header *bdb)
> > +parse_general_definitions(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_general_definitions *defs;
> >  	struct intel_bios_encoder_data *devdata;
> > @@ -2097,7 +2204,7 @@ parse_general_definitions(struct drm_i915_private *i915,
> >  	u16 block_size;
> >  	int bus_pin;
> >  
> > -	defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
> > +	defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
> >  	if (!defs) {
> >  		drm_dbg_kms(&i915->drm,
> >  			    "No general definition block is found, no devices defined.\n");
> > @@ -2466,6 +2573,7 @@ void intel_bios_init(struct drm_i915_private *i915)
> >  	const struct bdb_header *bdb;
> >  
> >  	INIT_LIST_HEAD(&i915->vbt.display_devices);
> > +	INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
> >  
> >  	if (!HAS_DISPLAY(i915)) {
> >  		drm_dbg_kms(&i915->drm,
> > @@ -2499,22 +2607,24 @@ void intel_bios_init(struct drm_i915_private *i915)
> >  		    "VBT signature \"%.*s\", BDB version %d\n",
> >  		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
> >  
> > +	init_bdb_blocks(i915, bdb);
> > +
> >  	/* Grab useful general definitions */
> > -	parse_general_features(i915, bdb);
> > -	parse_general_definitions(i915, bdb);
> > -	parse_panel_options(i915, bdb);
> > +	parse_general_features(i915);
> > +	parse_general_definitions(i915);
> > +	parse_panel_options(i915);
> >  	parse_panel_dtd(i915, bdb);
> > -	parse_lfp_backlight(i915, bdb);
> > -	parse_sdvo_panel_data(i915, bdb);
> > -	parse_driver_features(i915, bdb);
> > -	parse_power_conservation_features(i915, bdb);
> > -	parse_edp(i915, bdb);
> > -	parse_psr(i915, bdb);
> > -	parse_mipi_config(i915, bdb);
> > -	parse_mipi_sequence(i915, bdb);
> > +	parse_lfp_backlight(i915);
> > +	parse_sdvo_panel_data(i915);
> > +	parse_driver_features(i915);
> > +	parse_power_conservation_features(i915);
> > +	parse_edp(i915);
> > +	parse_psr(i915);
> > +	parse_mipi_config(i915);
> > +	parse_mipi_sequence(i915);
> >  
> >  	/* Depends on child device list */
> > -	parse_compression_parameters(i915, bdb);
> > +	parse_compression_parameters(i915);
> >  
> >  out:
> >  	if (!vbt) {
> > @@ -2536,14 +2646,20 @@ void intel_bios_init(struct drm_i915_private *i915)
> >   */
> >  void intel_bios_driver_remove(struct drm_i915_private *i915)
> >  {
> > -	struct intel_bios_encoder_data *devdata, *n;
> > +	struct intel_bios_encoder_data *devdata, *nd;
> > +	struct bdb_block_entry *entry, *ne;
> >  
> > -	list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
> > +	list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
> >  		list_del(&devdata->node);
> >  		kfree(devdata->dsc);
> >  		kfree(devdata);
> >  	}
> >  
> > +	list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
> > +		list_del(&entry->node);
> > +		kfree(entry);
> > +	}
> > +
> >  	kfree(i915->vbt.sdvo_lvds_vbt_mode);
> >  	i915->vbt.sdvo_lvds_vbt_mode = NULL;
> >  	kfree(i915->vbt.lfp_lvds_vbt_mode);
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 06e7c2802c5e..9274417cd87a 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -380,6 +380,7 @@ struct intel_vbt_data {
> >  	int crt_ddc_pin;
> >  
> >  	struct list_head display_devices;
> > +	struct list_head bdb_blocks;
> >  
> >  	struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
> >  	struct sdvo_device_mapping sdvo_mappings[2];
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 02/22] drm/i915/bios: Make copies of VBT data blocks
  2022-04-07 11:18       ` Ville Syrjälä
@ 2022-04-07 12:06         ` Jani Nikula
  2022-04-07 12:23           ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 12:06 UTC (permalink / raw)
  To: Ville Syrjälä; +Cc: intel-gfx

On Thu, 07 Apr 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> On Thu, Apr 07, 2022 at 01:23:38PM +0300, Jani Nikula wrote:
>> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
>> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> >
>> > Make a copy of each VB data block with a guaranteed minimum
>> > size. The extra (if any) will just be left zeroed.
>> >
>> > This means we don't have to worry about going out of bounds
>> > when accessing any of the structure members. Otherwise that
>> > could easliy happen if we simply get the version check wrong,
>> > or if the VBT is broken/malicious.
>> >
>> > v2: Don't do arithmetic between bdb header and copy
>> >     of the LFP data block (Jani)
>> > v3: Make all the copies up front
>> > v4: Only WARN about min_size==0 if we found the block
>> >
>> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > ---
>> >  drivers/gpu/drm/i915/display/intel_bios.c | 230 ++++++++++++++++------
>> >  drivers/gpu/drm/i915/i915_drv.h           |   1 +
>> >  2 files changed, 174 insertions(+), 57 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
>> > index 5518f4cfa1b1..068978734e3b 100644
>> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
>> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
>> > @@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
>> >  }
>> >  
>> >  static const void *
>> > -find_section(const void *_bdb, enum bdb_block_id section_id)
>> > +find_raw_section(const void *_bdb, enum bdb_block_id section_id)
>> >  {
>> >  	const struct bdb_header *bdb = _bdb;
>> >  	const u8 *base = _bdb;
>> > @@ -118,6 +118,124 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
>> >  	return NULL;
>> >  }
>> >  
>> > +/*
>> > + * Offset from the start of BDB to the start of the
>> > + * block data (just past the block header).
>> > + */
>> > +static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
>> > +{
>> > +	const void *block;
>> > +
>> > +	block = find_raw_section(bdb, section_id);
>> > +	if (!block)
>> > +		return 0;
>> > +
>> > +	return block - bdb;
>> > +}
>> > +
>> > +struct bdb_block_entry {
>> > +	struct list_head node;
>> > +	enum bdb_block_id section_id;
>> > +	u8 data[];
>> > +};
>> > +
>> > +static const void *
>> > +find_section(struct drm_i915_private *i915,
>> > +	     enum bdb_block_id section_id)
>> > +{
>> > +	struct bdb_block_entry *entry;
>> > +
>> > +	list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
>> > +		if (entry->section_id == section_id)
>> > +			return entry->data + 3;
>> > +	}
>> > +
>> 
>> Failing to find the section_id in the list above, perhaps this should
>> check if the section_id is present in bdb_blocks[] and complain
>> loudly. If we fail to add a section there, this will never find
>> it. I.e. we should never call find_section() on a section_id that isn't
>> present in bdb_blocks[].
>
> That's perfectly legit. Eg. old VBTs are always missing a lot
> of the eDP related blocks.
>
> What we could do is add some kind of dummy block into the list
> for every block we've initialized, whether we found it or not.
> With that we could complain if find_section() gets called on
> anything that we didn't try to duplicate.

I mean if we don't find it in the list, we can check the bdb_blocks[]
array if we even have it in our initialization list.

BR,
Jani.


>
>> 
>> I also dislike the +/- 3 here and there.
>
> Yeah, I was pondering about defining a structure that actually includes
> the BDB block header and try to replace all the magic +/-3 stuff with
> that. But didn't feel like bloating this series any further right now.
>
>> 
>> But both of these can be cleaned up later.
>> 
>> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
>> 
>> 
>> > +	return NULL;
>> > +}
>> > +
>> > +static const struct {
>> > +	enum bdb_block_id section_id;
>> > +	size_t min_size;
>> > +} bdb_blocks[] = {
>> > +	{ .section_id = BDB_GENERAL_FEATURES,
>> > +	  .min_size = sizeof(struct bdb_general_features), },
>> > +	{ .section_id = BDB_GENERAL_DEFINITIONS,
>> > +	  .min_size = sizeof(struct bdb_general_definitions), },
>> > +	{ .section_id = BDB_PSR,
>> > +	  .min_size = sizeof(struct bdb_psr), },
>> > +	{ .section_id = BDB_DRIVER_FEATURES,
>> > +	  .min_size = sizeof(struct bdb_driver_features), },
>> > +	{ .section_id = BDB_SDVO_LVDS_OPTIONS,
>> > +	  .min_size = sizeof(struct bdb_sdvo_lvds_options), },
>> > +	{ .section_id = BDB_SDVO_PANEL_DTDS,
>> > +	  .min_size = sizeof(struct bdb_sdvo_panel_dtds), },
>> > +	{ .section_id = BDB_EDP,
>> > +	  .min_size = sizeof(struct bdb_edp), },
>> > +	{ .section_id = BDB_LVDS_OPTIONS,
>> > +	  .min_size = sizeof(struct bdb_lvds_options), },
>> > +	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
>> > +	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
>> > +	{ .section_id = BDB_LVDS_LFP_DATA,
>> > +	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
>> > +	{ .section_id = BDB_LVDS_BACKLIGHT,
>> > +	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
>> > +	{ .section_id = BDB_LFP_POWER,
>> > +	  .min_size = sizeof(struct bdb_lfp_power), },
>> > +	{ .section_id = BDB_MIPI_CONFIG,
>> > +	  .min_size = sizeof(struct bdb_mipi_config), },
>> > +	{ .section_id = BDB_MIPI_SEQUENCE,
>> > +	  .min_size = sizeof(struct bdb_mipi_sequence) },
>> > +	{ .section_id = BDB_COMPRESSION_PARAMETERS,
>> > +	  .min_size = sizeof(struct bdb_compression_parameters), },
>> > +	{ .section_id = BDB_GENERIC_DTD,
>> > +	  .min_size = sizeof(struct bdb_generic_dtd), },
>> > +};
>> > +
>> > +static void
>> > +init_bdb_block(struct drm_i915_private *i915,
>> > +	       const void *bdb, enum bdb_block_id section_id,
>> > +	       size_t min_size)
>> > +{
>> > +	struct bdb_block_entry *entry;
>> > +	const void *block;
>> > +	size_t block_size;
>> > +
>> > +	block = find_raw_section(bdb, section_id);
>> > +	if (!block)
>> > +		return;
>> > +
>> > +	drm_WARN(&i915->drm, min_size == 0,
>> > +		 "Block %d min_size is zero\n", section_id);
>> > +
>> > +	block_size = get_blocksize(block);
>> > +
>> > +	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
>> > +			GFP_KERNEL);
>> > +	if (!entry)
>> > +		return;
>> > +
>> > +	entry->section_id = section_id;
>> > +	memcpy(entry->data, block - 3, block_size + 3);
>> > +
>> > +	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
>> > +		    section_id, block_size, min_size);
>> > +
>> > +	list_add_tail(&entry->node, &i915->vbt.bdb_blocks);
>> > +}
>> > +
>> > +static void init_bdb_blocks(struct drm_i915_private *i915,
>> > +			    const void *bdb)
>> > +{
>> > +	int i;
>> > +
>> > +	for (i = 0; i < ARRAY_SIZE(bdb_blocks); i++) {
>> > +		enum bdb_block_id section_id = bdb_blocks[i].section_id;
>> > +		size_t min_size = bdb_blocks[i].min_size;
>> > +
>> > +		init_bdb_block(i915, bdb, section_id, min_size);
>> > +	}
>> > +}
>> > +
>> >  static void
>> >  fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
>> >  			const struct lvds_dvo_timing *dvo_timing)
>> > @@ -199,7 +317,7 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
>> >  		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
>> >  		   int index)
>> >  {
>> > -	size_t data_ofs = (const u8 *)data - (const u8 *)bdb;
>> > +	size_t data_ofs = block_offset(bdb, BDB_LVDS_LFP_DATA);
>> >  	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
>> >  	size_t ofs;
>> >  
>> > @@ -214,15 +332,14 @@ get_lvds_fp_timing(const struct bdb_header *bdb,
>> >  
>> >  /* Parse general panel options */
>> >  static void
>> > -parse_panel_options(struct drm_i915_private *i915,
>> > -		    const struct bdb_header *bdb)
>> > +parse_panel_options(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_lvds_options *lvds_options;
>> >  	int panel_type;
>> >  	int drrs_mode;
>> >  	int ret;
>> >  
>> > -	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
>> > +	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
>> >  	if (!lvds_options)
>> >  		return;
>> >  
>> > @@ -285,11 +402,11 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
>> >  	struct drm_display_mode *panel_fixed_mode;
>> >  	int panel_type = i915->vbt.panel_type;
>> >  
>> > -	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
>> > +	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
>> >  	if (!lvds_lfp_data)
>> >  		return;
>> >  
>> > -	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
>> > +	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
>> >  	if (!lvds_lfp_data_ptrs)
>> >  		return;
>> >  
>> > @@ -325,15 +442,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
>> >  }
>> >  
>> >  static void
>> > -parse_generic_dtd(struct drm_i915_private *i915,
>> > -		  const struct bdb_header *bdb)
>> > +parse_generic_dtd(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_generic_dtd *generic_dtd;
>> >  	const struct generic_dtd_entry *dtd;
>> >  	struct drm_display_mode *panel_fixed_mode;
>> >  	int num_dtd;
>> >  
>> > -	generic_dtd = find_section(bdb, BDB_GENERIC_DTD);
>> > +	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
>> >  	if (!generic_dtd)
>> >  		return;
>> >  
>> > @@ -416,21 +532,20 @@ parse_panel_dtd(struct drm_i915_private *i915,
>> >  	 * back to trying the old LFP block if that fails.
>> >  	 */
>> >  	if (i915->vbt.version >= 229)
>> > -		parse_generic_dtd(i915, bdb);
>> > +		parse_generic_dtd(i915);
>> >  	if (!i915->vbt.lfp_lvds_vbt_mode)
>> >  		parse_lfp_panel_dtd(i915, bdb);
>> >  }
>> >  
>> >  static void
>> > -parse_lfp_backlight(struct drm_i915_private *i915,
>> > -		    const struct bdb_header *bdb)
>> > +parse_lfp_backlight(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_lfp_backlight_data *backlight_data;
>> >  	const struct lfp_backlight_data_entry *entry;
>> >  	int panel_type = i915->vbt.panel_type;
>> >  	u16 level;
>> >  
>> > -	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
>> > +	backlight_data = find_section(i915, BDB_LVDS_BACKLIGHT);
>> >  	if (!backlight_data)
>> >  		return;
>> >  
>> > @@ -514,8 +629,7 @@ parse_lfp_backlight(struct drm_i915_private *i915,
>> >  
>> >  /* Try to find sdvo panel data */
>> >  static void
>> > -parse_sdvo_panel_data(struct drm_i915_private *i915,
>> > -		      const struct bdb_header *bdb)
>> > +parse_sdvo_panel_data(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_sdvo_panel_dtds *dtds;
>> >  	struct drm_display_mode *panel_fixed_mode;
>> > @@ -531,14 +645,14 @@ parse_sdvo_panel_data(struct drm_i915_private *i915,
>> >  	if (index == -1) {
>> >  		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
>> >  
>> > -		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
>> > +		sdvo_lvds_options = find_section(i915, BDB_SDVO_LVDS_OPTIONS);
>> >  		if (!sdvo_lvds_options)
>> >  			return;
>> >  
>> >  		index = sdvo_lvds_options->panel_type;
>> >  	}
>> >  
>> > -	dtds = find_section(bdb, BDB_SDVO_PANEL_DTDS);
>> > +	dtds = find_section(i915, BDB_SDVO_PANEL_DTDS);
>> >  	if (!dtds)
>> >  		return;
>> >  
>> > @@ -570,12 +684,11 @@ static int intel_bios_ssc_frequency(struct drm_i915_private *i915,
>> >  }
>> >  
>> >  static void
>> > -parse_general_features(struct drm_i915_private *i915,
>> > -		       const struct bdb_header *bdb)
>> > +parse_general_features(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_general_features *general;
>> >  
>> > -	general = find_section(bdb, BDB_GENERAL_FEATURES);
>> > +	general = find_section(i915, BDB_GENERAL_FEATURES);
>> >  	if (!general)
>> >  		return;
>> >  
>> > @@ -695,12 +808,11 @@ parse_sdvo_device_mapping(struct drm_i915_private *i915)
>> >  }
>> >  
>> >  static void
>> > -parse_driver_features(struct drm_i915_private *i915,
>> > -		      const struct bdb_header *bdb)
>> > +parse_driver_features(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_driver_features *driver;
>> >  
>> > -	driver = find_section(bdb, BDB_DRIVER_FEATURES);
>> > +	driver = find_section(i915, BDB_DRIVER_FEATURES);
>> >  	if (!driver)
>> >  		return;
>> >  
>> > @@ -747,8 +859,7 @@ parse_driver_features(struct drm_i915_private *i915,
>> >  }
>> >  
>> >  static void
>> > -parse_power_conservation_features(struct drm_i915_private *i915,
>> > -				  const struct bdb_header *bdb)
>> > +parse_power_conservation_features(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_lfp_power *power;
>> >  	u8 panel_type = i915->vbt.panel_type;
>> > @@ -756,7 +867,7 @@ parse_power_conservation_features(struct drm_i915_private *i915,
>> >  	if (i915->vbt.version < 228)
>> >  		return;
>> >  
>> > -	power = find_section(bdb, BDB_LFP_POWER);
>> > +	power = find_section(i915, BDB_LFP_POWER);
>> >  	if (!power)
>> >  		return;
>> >  
>> > @@ -776,14 +887,14 @@ parse_power_conservation_features(struct drm_i915_private *i915,
>> >  }
>> >  
>> >  static void
>> > -parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
>> > +parse_edp(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_edp *edp;
>> >  	const struct edp_power_seq *edp_pps;
>> >  	const struct edp_fast_link_params *edp_link_params;
>> >  	int panel_type = i915->vbt.panel_type;
>> >  
>> > -	edp = find_section(bdb, BDB_EDP);
>> > +	edp = find_section(i915, BDB_EDP);
>> >  	if (!edp)
>> >  		return;
>> >  
>> > @@ -894,13 +1005,13 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb)
>> >  }
>> >  
>> >  static void
>> > -parse_psr(struct drm_i915_private *i915, const struct bdb_header *bdb)
>> > +parse_psr(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_psr *psr;
>> >  	const struct psr_table *psr_table;
>> >  	int panel_type = i915->vbt.panel_type;
>> >  
>> > -	psr = find_section(bdb, BDB_PSR);
>> > +	psr = find_section(i915, BDB_PSR);
>> >  	if (!psr) {
>> >  		drm_dbg_kms(&i915->drm, "No PSR BDB found.\n");
>> >  		return;
>> > @@ -1034,8 +1145,7 @@ static void parse_dsi_backlight_ports(struct drm_i915_private *i915,
>> >  }
>> >  
>> >  static void
>> > -parse_mipi_config(struct drm_i915_private *i915,
>> > -		  const struct bdb_header *bdb)
>> > +parse_mipi_config(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_mipi_config *start;
>> >  	const struct mipi_config *config;
>> > @@ -1058,7 +1168,7 @@ parse_mipi_config(struct drm_i915_private *i915,
>> >  	/* Parse #52 for panel index used from panel_type already
>> >  	 * parsed
>> >  	 */
>> > -	start = find_section(bdb, BDB_MIPI_CONFIG);
>> > +	start = find_section(i915, BDB_MIPI_CONFIG);
>> >  	if (!start) {
>> >  		drm_dbg_kms(&i915->drm, "No MIPI config BDB found");
>> >  		return;
>> > @@ -1354,8 +1464,7 @@ static void fixup_mipi_sequences(struct drm_i915_private *i915)
>> >  }
>> >  
>> >  static void
>> > -parse_mipi_sequence(struct drm_i915_private *i915,
>> > -		    const struct bdb_header *bdb)
>> > +parse_mipi_sequence(struct drm_i915_private *i915)
>> >  {
>> >  	int panel_type = i915->vbt.panel_type;
>> >  	const struct bdb_mipi_sequence *sequence;
>> > @@ -1368,7 +1477,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
>> >  	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
>> >  		return;
>> >  
>> > -	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
>> > +	sequence = find_section(i915, BDB_MIPI_SEQUENCE);
>> >  	if (!sequence) {
>> >  		drm_dbg_kms(&i915->drm,
>> >  			    "No MIPI Sequence found, parsing complete\n");
>> > @@ -1439,8 +1548,7 @@ parse_mipi_sequence(struct drm_i915_private *i915,
>> >  }
>> >  
>> >  static void
>> > -parse_compression_parameters(struct drm_i915_private *i915,
>> > -			     const struct bdb_header *bdb)
>> > +parse_compression_parameters(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_compression_parameters *params;
>> >  	struct intel_bios_encoder_data *devdata;
>> > @@ -1451,7 +1559,7 @@ parse_compression_parameters(struct drm_i915_private *i915,
>> >  	if (i915->vbt.version < 198)
>> >  		return;
>> >  
>> > -	params = find_section(bdb, BDB_COMPRESSION_PARAMETERS);
>> > +	params = find_section(i915, BDB_COMPRESSION_PARAMETERS);
>> >  	if (params) {
>> >  		/* Sanity checks */
>> >  		if (params->entry_size != sizeof(params->data[0])) {
>> > @@ -2086,8 +2194,7 @@ static void parse_ddi_ports(struct drm_i915_private *i915)
>> >  }
>> >  
>> >  static void
>> > -parse_general_definitions(struct drm_i915_private *i915,
>> > -			  const struct bdb_header *bdb)
>> > +parse_general_definitions(struct drm_i915_private *i915)
>> >  {
>> >  	const struct bdb_general_definitions *defs;
>> >  	struct intel_bios_encoder_data *devdata;
>> > @@ -2097,7 +2204,7 @@ parse_general_definitions(struct drm_i915_private *i915,
>> >  	u16 block_size;
>> >  	int bus_pin;
>> >  
>> > -	defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
>> > +	defs = find_section(i915, BDB_GENERAL_DEFINITIONS);
>> >  	if (!defs) {
>> >  		drm_dbg_kms(&i915->drm,
>> >  			    "No general definition block is found, no devices defined.\n");
>> > @@ -2466,6 +2573,7 @@ void intel_bios_init(struct drm_i915_private *i915)
>> >  	const struct bdb_header *bdb;
>> >  
>> >  	INIT_LIST_HEAD(&i915->vbt.display_devices);
>> > +	INIT_LIST_HEAD(&i915->vbt.bdb_blocks);
>> >  
>> >  	if (!HAS_DISPLAY(i915)) {
>> >  		drm_dbg_kms(&i915->drm,
>> > @@ -2499,22 +2607,24 @@ void intel_bios_init(struct drm_i915_private *i915)
>> >  		    "VBT signature \"%.*s\", BDB version %d\n",
>> >  		    (int)sizeof(vbt->signature), vbt->signature, i915->vbt.version);
>> >  
>> > +	init_bdb_blocks(i915, bdb);
>> > +
>> >  	/* Grab useful general definitions */
>> > -	parse_general_features(i915, bdb);
>> > -	parse_general_definitions(i915, bdb);
>> > -	parse_panel_options(i915, bdb);
>> > +	parse_general_features(i915);
>> > +	parse_general_definitions(i915);
>> > +	parse_panel_options(i915);
>> >  	parse_panel_dtd(i915, bdb);
>> > -	parse_lfp_backlight(i915, bdb);
>> > -	parse_sdvo_panel_data(i915, bdb);
>> > -	parse_driver_features(i915, bdb);
>> > -	parse_power_conservation_features(i915, bdb);
>> > -	parse_edp(i915, bdb);
>> > -	parse_psr(i915, bdb);
>> > -	parse_mipi_config(i915, bdb);
>> > -	parse_mipi_sequence(i915, bdb);
>> > +	parse_lfp_backlight(i915);
>> > +	parse_sdvo_panel_data(i915);
>> > +	parse_driver_features(i915);
>> > +	parse_power_conservation_features(i915);
>> > +	parse_edp(i915);
>> > +	parse_psr(i915);
>> > +	parse_mipi_config(i915);
>> > +	parse_mipi_sequence(i915);
>> >  
>> >  	/* Depends on child device list */
>> > -	parse_compression_parameters(i915, bdb);
>> > +	parse_compression_parameters(i915);
>> >  
>> >  out:
>> >  	if (!vbt) {
>> > @@ -2536,14 +2646,20 @@ void intel_bios_init(struct drm_i915_private *i915)
>> >   */
>> >  void intel_bios_driver_remove(struct drm_i915_private *i915)
>> >  {
>> > -	struct intel_bios_encoder_data *devdata, *n;
>> > +	struct intel_bios_encoder_data *devdata, *nd;
>> > +	struct bdb_block_entry *entry, *ne;
>> >  
>> > -	list_for_each_entry_safe(devdata, n, &i915->vbt.display_devices, node) {
>> > +	list_for_each_entry_safe(devdata, nd, &i915->vbt.display_devices, node) {
>> >  		list_del(&devdata->node);
>> >  		kfree(devdata->dsc);
>> >  		kfree(devdata);
>> >  	}
>> >  
>> > +	list_for_each_entry_safe(entry, ne, &i915->vbt.bdb_blocks, node) {
>> > +		list_del(&entry->node);
>> > +		kfree(entry);
>> > +	}
>> > +
>> >  	kfree(i915->vbt.sdvo_lvds_vbt_mode);
>> >  	i915->vbt.sdvo_lvds_vbt_mode = NULL;
>> >  	kfree(i915->vbt.lfp_lvds_vbt_mode);
>> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
>> > index 06e7c2802c5e..9274417cd87a 100644
>> > --- a/drivers/gpu/drm/i915/i915_drv.h
>> > +++ b/drivers/gpu/drm/i915/i915_drv.h
>> > @@ -380,6 +380,7 @@ struct intel_vbt_data {
>> >  	int crt_ddc_pin;
>> >  
>> >  	struct list_head display_devices;
>> > +	struct list_head bdb_blocks;
>> >  
>> >  	struct intel_bios_encoder_data *ports[I915_MAX_PORTS]; /* Non-NULL if port present. */
>> >  	struct sdvo_device_mapping sdvo_mappings[2];
>> 
>> -- 
>> Jani Nikula, Intel Open Source Graphics Center

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 02/22] drm/i915/bios: Make copies of VBT data blocks
  2022-04-07 12:06         ` Jani Nikula
@ 2022-04-07 12:23           ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-07 12:23 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 03:06:04PM +0300, Jani Nikula wrote:
> On Thu, 07 Apr 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Thu, Apr 07, 2022 at 01:23:38PM +0300, Jani Nikula wrote:
> >> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> >> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >
> >> > Make a copy of each VB data block with a guaranteed minimum
> >> > size. The extra (if any) will just be left zeroed.
> >> >
> >> > This means we don't have to worry about going out of bounds
> >> > when accessing any of the structure members. Otherwise that
> >> > could easliy happen if we simply get the version check wrong,
> >> > or if the VBT is broken/malicious.
> >> >
> >> > v2: Don't do arithmetic between bdb header and copy
> >> >     of the LFP data block (Jani)
> >> > v3: Make all the copies up front
> >> > v4: Only WARN about min_size==0 if we found the block
> >> >
> >> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> > ---
> >> >  drivers/gpu/drm/i915/display/intel_bios.c | 230 ++++++++++++++++------
> >> >  drivers/gpu/drm/i915/i915_drv.h           |   1 +
> >> >  2 files changed, 174 insertions(+), 57 deletions(-)
> >> >
> >> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> >> > index 5518f4cfa1b1..068978734e3b 100644
> >> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> >> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> >> > @@ -88,7 +88,7 @@ static u32 get_blocksize(const void *block_data)
> >> >  }
> >> >  
> >> >  static const void *
> >> > -find_section(const void *_bdb, enum bdb_block_id section_id)
> >> > +find_raw_section(const void *_bdb, enum bdb_block_id section_id)
> >> >  {
> >> >  	const struct bdb_header *bdb = _bdb;
> >> >  	const u8 *base = _bdb;
> >> > @@ -118,6 +118,124 @@ find_section(const void *_bdb, enum bdb_block_id section_id)
> >> >  	return NULL;
> >> >  }
> >> >  
> >> > +/*
> >> > + * Offset from the start of BDB to the start of the
> >> > + * block data (just past the block header).
> >> > + */
> >> > +static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
> >> > +{
> >> > +	const void *block;
> >> > +
> >> > +	block = find_raw_section(bdb, section_id);
> >> > +	if (!block)
> >> > +		return 0;
> >> > +
> >> > +	return block - bdb;
> >> > +}
> >> > +
> >> > +struct bdb_block_entry {
> >> > +	struct list_head node;
> >> > +	enum bdb_block_id section_id;
> >> > +	u8 data[];
> >> > +};
> >> > +
> >> > +static const void *
> >> > +find_section(struct drm_i915_private *i915,
> >> > +	     enum bdb_block_id section_id)
> >> > +{
> >> > +	struct bdb_block_entry *entry;
> >> > +
> >> > +	list_for_each_entry(entry, &i915->vbt.bdb_blocks, node) {
> >> > +		if (entry->section_id == section_id)
> >> > +			return entry->data + 3;
> >> > +	}
> >> > +
> >> 
> >> Failing to find the section_id in the list above, perhaps this should
> >> check if the section_id is present in bdb_blocks[] and complain
> >> loudly. If we fail to add a section there, this will never find
> >> it. I.e. we should never call find_section() on a section_id that isn't
> >> present in bdb_blocks[].
> >
> > That's perfectly legit. Eg. old VBTs are always missing a lot
> > of the eDP related blocks.
> >
> > What we could do is add some kind of dummy block into the list
> > for every block we've initialized, whether we found it or not.
> > With that we could complain if find_section() gets called on
> > anything that we didn't try to duplicate.
> 
> I mean if we don't find it in the list, we can check the bdb_blocks[]
> array if we even have it in our initialization list.

Ah, yeah we could do that I suppose.

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-06 13:39   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
@ 2022-04-07 12:24     ` Jani Nikula
  2022-04-07 12:29       ` Ville Syrjälä
  2022-04-07 16:53     ` Jani Nikula
  1 sibling, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 12:24 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Modern VBTs no longer contain the LFP data table pointers
> block (41). We are expecting to have one in order to be able
> to parse the LFP data block (42), so let's make one up.

Bspec says, "These fields are used by the BMP tool to locate the tables
in block 42 and present in its GUI."

Sounds like an alternative would be to always just parse block 42
directly instead of validating/generating block 41 for that?

Maybe it's easier to go with what you've done here now, and reconsider
in the future. *shrug*.

BR,
Jani.


>
> Since the fp_timing table has variable size we must somehow
> determine its size. Rather than just hardcode it we look for
> the terminator bytes (0xffff) to figure out where each table
> entry starts. dvo_timing, panel_pnp_id, and panel_name are
> expected to have fixed size.
>
> This has been observed on various machines, eg. TGL with BDB
> version 240, CML with BDB version 231, etc. The most recent
> VBT I've observed that still had block 41 had BDB version
> 228. So presumably the cutoff (if an exact cutoff even exists)
> is somewhere around BDB version 229-231.
>
> v2: kfree the thing we allocated, not the thing+3 bytes
> v3: Do the debugprint only if we found the LFP data block
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 136 +++++++++++++++++++++-
>  1 file changed, 135 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 8b118c54314d..d32091dad1b0 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -310,16 +310,146 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
>  	return validate_lfp_data_ptrs(bdb, ptrs);
>  }
>  
> +static const void *find_fp_timing_terminator(const u8 *data, int size)
> +{
> +	int i;
> +
> +	if (!data)
> +		return NULL;
> +
> +	for (i = 0; i < size - 1; i++) {
> +		if (data[i] == 0xff && data[i+1] == 0xff)
> +			return &data[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
> +			     int table_size, int total_size)
> +{
> +	if (total_size < table_size)
> +		return total_size;
> +
> +	table->table_size = table_size;
> +	table->offset = total_size - table_size;
> +
> +	return total_size - table_size;
> +}
> +
> +static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
> +			      const struct lvds_lfp_data_ptr_table *prev,
> +			      int size)
> +{
> +	next->table_size = prev->table_size;
> +	next->offset = prev->offset + size;
> +}
> +
> +static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
> +				    const void *bdb)
> +{
> +	int i, size, table_size, block_size, offset;
> +	const void *t0, *t1, *block;
> +	struct bdb_lvds_lfp_data_ptrs *ptrs;
> +	void *ptrs_block;
> +
> +	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
> +	if (!block)
> +		return NULL;
> +
> +	drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
> +
> +	block_size = get_blocksize(block);
> +
> +	size = block_size;
> +	t0 = find_fp_timing_terminator(block, size);
> +
> +	size -= t0 - block - 2;
> +	t1 = find_fp_timing_terminator(t0 + 2, size);
> +
> +	if (!t0 || !t1)
> +		return NULL;
> +
> +	size = t1 - t0;
> +	if (size * 16 > block_size)
> +		return NULL;
> +
> +	ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
> +	if (!ptrs_block)
> +		return NULL;
> +
> +	*(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS;
> +	*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
> +	ptrs = ptrs_block + 3;
> +
> +	table_size = sizeof(struct lvds_pnp_id);
> +	size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
> +
> +	table_size = sizeof(struct lvds_dvo_timing);
> +	size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
> +
> +	table_size = t0 - block + 2;
> +	size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
> +
> +	if (ptrs->ptr[0].fp_timing.table_size)
> +		ptrs->lvds_entries++;
> +	if (ptrs->ptr[0].dvo_timing.table_size)
> +		ptrs->lvds_entries++;
> +	if (ptrs->ptr[0].panel_pnp_id.table_size)
> +		ptrs->lvds_entries++;
> +
> +	if (size != 0 || ptrs->lvds_entries != 3) {
> +		kfree(ptrs);
> +		return NULL;
> +	}
> +
> +	size = t1 - t0;
> +	for (i = 1; i < 16; i++) {
> +		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
> +		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
> +		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
> +	}
> +
> +	size = t1 - t0;
> +	table_size = sizeof(struct lvds_lfp_panel_name);
> +
> +	if (16 * (size + table_size) <= block_size) {
> +		ptrs->panel_name.table_size = table_size;
> +		ptrs->panel_name.offset = size * 16;
> +	}
> +
> +	offset = block - bdb;
> +
> +	for (i = 0; i < 16; i++) {
> +		ptrs->ptr[i].fp_timing.offset += offset;
> +		ptrs->ptr[i].dvo_timing.offset += offset;
> +		ptrs->ptr[i].panel_pnp_id.offset += offset;
> +	}
> +
> +	if (ptrs->panel_name.table_size)
> +		ptrs->panel_name.offset += offset;
> +
> +	return ptrs_block;
> +}
> +
>  static void
>  init_bdb_block(struct drm_i915_private *i915,
>  	       const void *bdb, enum bdb_block_id section_id,
>  	       size_t min_size)
>  {
>  	struct bdb_block_entry *entry;
> +	void *temp_block = NULL;
>  	const void *block;
>  	size_t block_size;
>  
>  	block = find_raw_section(bdb, section_id);
> +
> +	/* Modern VBTs lack the LFP data table pointers block, make one up */
> +	if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) {
> +		temp_block = generate_lfp_data_ptrs(i915, bdb);
> +		if (temp_block)
> +			block = temp_block + 3;
> +	}
>  	if (!block)
>  		return;
>  
> @@ -330,12 +460,16 @@ init_bdb_block(struct drm_i915_private *i915,
>  
>  	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
>  			GFP_KERNEL);
> -	if (!entry)
> +	if (!entry) {
> +		kfree(temp_block);
>  		return;
> +	}
>  
>  	entry->section_id = section_id;
>  	memcpy(entry->data, block - 3, block_size + 3);
>  
> +	kfree(temp_block);
> +
>  	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
>  		    section_id, block_size, min_size);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-07 12:24     ` Jani Nikula
@ 2022-04-07 12:29       ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-07 12:29 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 03:24:15PM +0300, Jani Nikula wrote:
> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Modern VBTs no longer contain the LFP data table pointers
> > block (41). We are expecting to have one in order to be able
> > to parse the LFP data block (42), so let's make one up.
> 
> Bspec says, "These fields are used by the BMP tool to locate the tables
> in block 42 and present in its GUI."
> 
> Sounds like an alternative would be to always just parse block 42
> directly instead of validating/generating block 41 for that?

We can't since the fp_timing table entries don't have a fixed size.
Well, maybe we could for some modern VBTs where we perhaps can assume
a fixed size. But then we'd have two totally different ways to parse
block 42 which I don't like.

> 
> Maybe it's easier to go with what you've done here now, and reconsider
> in the future. *shrug*.
> 
> BR,
> Jani.
> 
> 
> >
> > Since the fp_timing table has variable size we must somehow
> > determine its size. Rather than just hardcode it we look for
> > the terminator bytes (0xffff) to figure out where each table
> > entry starts. dvo_timing, panel_pnp_id, and panel_name are
> > expected to have fixed size.
> >
> > This has been observed on various machines, eg. TGL with BDB
> > version 240, CML with BDB version 231, etc. The most recent
> > VBT I've observed that still had block 41 had BDB version
> > 228. So presumably the cutoff (if an exact cutoff even exists)
> > is somewhere around BDB version 229-231.
> >
> > v2: kfree the thing we allocated, not the thing+3 bytes
> > v3: Do the debugprint only if we found the LFP data block
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c | 136 +++++++++++++++++++++-
> >  1 file changed, 135 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 8b118c54314d..d32091dad1b0 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -310,16 +310,146 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
> >  	return validate_lfp_data_ptrs(bdb, ptrs);
> >  }
> >  
> > +static const void *find_fp_timing_terminator(const u8 *data, int size)
> > +{
> > +	int i;
> > +
> > +	if (!data)
> > +		return NULL;
> > +
> > +	for (i = 0; i < size - 1; i++) {
> > +		if (data[i] == 0xff && data[i+1] == 0xff)
> > +			return &data[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
> > +			     int table_size, int total_size)
> > +{
> > +	if (total_size < table_size)
> > +		return total_size;
> > +
> > +	table->table_size = table_size;
> > +	table->offset = total_size - table_size;
> > +
> > +	return total_size - table_size;
> > +}
> > +
> > +static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
> > +			      const struct lvds_lfp_data_ptr_table *prev,
> > +			      int size)
> > +{
> > +	next->table_size = prev->table_size;
> > +	next->offset = prev->offset + size;
> > +}
> > +
> > +static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
> > +				    const void *bdb)
> > +{
> > +	int i, size, table_size, block_size, offset;
> > +	const void *t0, *t1, *block;
> > +	struct bdb_lvds_lfp_data_ptrs *ptrs;
> > +	void *ptrs_block;
> > +
> > +	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
> > +	if (!block)
> > +		return NULL;
> > +
> > +	drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
> > +
> > +	block_size = get_blocksize(block);
> > +
> > +	size = block_size;
> > +	t0 = find_fp_timing_terminator(block, size);
> > +
> > +	size -= t0 - block - 2;
> > +	t1 = find_fp_timing_terminator(t0 + 2, size);
> > +
> > +	if (!t0 || !t1)
> > +		return NULL;
> > +
> > +	size = t1 - t0;
> > +	if (size * 16 > block_size)
> > +		return NULL;
> > +
> > +	ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
> > +	if (!ptrs_block)
> > +		return NULL;
> > +
> > +	*(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS;
> > +	*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
> > +	ptrs = ptrs_block + 3;
> > +
> > +	table_size = sizeof(struct lvds_pnp_id);
> > +	size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
> > +
> > +	table_size = sizeof(struct lvds_dvo_timing);
> > +	size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
> > +
> > +	table_size = t0 - block + 2;
> > +	size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
> > +
> > +	if (ptrs->ptr[0].fp_timing.table_size)
> > +		ptrs->lvds_entries++;
> > +	if (ptrs->ptr[0].dvo_timing.table_size)
> > +		ptrs->lvds_entries++;
> > +	if (ptrs->ptr[0].panel_pnp_id.table_size)
> > +		ptrs->lvds_entries++;
> > +
> > +	if (size != 0 || ptrs->lvds_entries != 3) {
> > +		kfree(ptrs);
> > +		return NULL;
> > +	}
> > +
> > +	size = t1 - t0;
> > +	for (i = 1; i < 16; i++) {
> > +		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
> > +		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
> > +		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
> > +	}
> > +
> > +	size = t1 - t0;
> > +	table_size = sizeof(struct lvds_lfp_panel_name);
> > +
> > +	if (16 * (size + table_size) <= block_size) {
> > +		ptrs->panel_name.table_size = table_size;
> > +		ptrs->panel_name.offset = size * 16;
> > +	}
> > +
> > +	offset = block - bdb;
> > +
> > +	for (i = 0; i < 16; i++) {
> > +		ptrs->ptr[i].fp_timing.offset += offset;
> > +		ptrs->ptr[i].dvo_timing.offset += offset;
> > +		ptrs->ptr[i].panel_pnp_id.offset += offset;
> > +	}
> > +
> > +	if (ptrs->panel_name.table_size)
> > +		ptrs->panel_name.offset += offset;
> > +
> > +	return ptrs_block;
> > +}
> > +
> >  static void
> >  init_bdb_block(struct drm_i915_private *i915,
> >  	       const void *bdb, enum bdb_block_id section_id,
> >  	       size_t min_size)
> >  {
> >  	struct bdb_block_entry *entry;
> > +	void *temp_block = NULL;
> >  	const void *block;
> >  	size_t block_size;
> >  
> >  	block = find_raw_section(bdb, section_id);
> > +
> > +	/* Modern VBTs lack the LFP data table pointers block, make one up */
> > +	if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) {
> > +		temp_block = generate_lfp_data_ptrs(i915, bdb);
> > +		if (temp_block)
> > +			block = temp_block + 3;
> > +	}
> >  	if (!block)
> >  		return;
> >  
> > @@ -330,12 +460,16 @@ init_bdb_block(struct drm_i915_private *i915,
> >  
> >  	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
> >  			GFP_KERNEL);
> > -	if (!entry)
> > +	if (!entry) {
> > +		kfree(temp_block);
> >  		return;
> > +	}
> >  
> >  	entry->section_id = section_id;
> >  	memcpy(entry->data, block - 3, block_size + 3);
> >  
> > +	kfree(temp_block);
> > +
> >  	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
> >  		    section_id, block_size, min_size);
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 04/22] drm/i915/bios: Validate LFP data table pointers
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 04/22] drm/i915/bios: Validate LFP data table pointers Ville Syrjala
@ 2022-04-07 16:07   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 16:07 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make sure the LFP data table pointers sane. Sensible looking
> table entries, everything points correctly into the data block,
> etc.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

I can't adequately describe my opinion about the design of the data
structures here. Sheesh.

Dunno why we keep struct lvds_lfp_data_entry and struct
bdb_lvds_lfp_data around, as they don't really reflect reality.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 82 ++++++++++++++++++++++-
>  1 file changed, 81 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 000544280c35..cd82ea4de8e1 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -133,6 +133,18 @@ static u32 block_offset(const void *bdb, enum bdb_block_id section_id)
>  	return block - bdb;
>  }
>  
> +/* size of the block excluding the header */
> +static u32 block_size(const void *bdb, enum bdb_block_id section_id)
> +{
> +	const void *block;
> +
> +	block = find_raw_section(bdb, section_id);
> +	if (!block)
> +		return 0;
> +
> +	return get_blocksize(block);
> +}
> +
>  struct bdb_block_entry {
>  	struct list_head node;
>  	enum bdb_block_id section_id;
> @@ -191,6 +203,74 @@ static const struct {
>  	  .min_size = sizeof(struct bdb_generic_dtd), },
>  };
>  
> +static bool validate_lfp_data_ptrs(const void *bdb,
> +				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
> +{
> +	int fp_timing_size, dvo_timing_size, panel_pnp_id_size;
> +	int data_block_size, lfp_data_size;
> +	int i;
> +
> +	data_block_size = block_size(bdb, BDB_LVDS_LFP_DATA);
> +	if (data_block_size == 0)
> +		return false;
> +
> +	/* always 3 indicating the presence of fp_timing+dvo_timing+panel_pnp_id */
> +	if (ptrs->lvds_entries != 3)
> +		return false;
> +
> +	fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
> +	dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
> +	panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
> +
> +	/* fp_timing has variable size */
> +	if (fp_timing_size < 32 ||
> +	    dvo_timing_size != sizeof(struct lvds_dvo_timing) ||
> +	    panel_pnp_id_size != sizeof(struct lvds_pnp_id))
> +		return false;
> +
> +	lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
> +	if (16 * lfp_data_size > data_block_size)
> +		return false;
> +
> +	/*
> +	 * Except for vlv/chv machines all real VBTs seem to have 6
> +	 * unaccounted bytes in the fp_timing table. And it doesn't
> +	 * appear to be a really intentional hole as the fp_timing
> +	 * 0xffff terminator is always within those 6 missing bytes.
> +	 */
> +	if (fp_timing_size + dvo_timing_size + panel_pnp_id_size != lfp_data_size &&
> +	    fp_timing_size + 6 + dvo_timing_size + panel_pnp_id_size != lfp_data_size)
> +		return false;
> +
> +	if (ptrs->ptr[0].fp_timing.offset + fp_timing_size > ptrs->ptr[0].dvo_timing.offset ||
> +	    ptrs->ptr[0].dvo_timing.offset + dvo_timing_size != ptrs->ptr[0].panel_pnp_id.offset ||
> +	    ptrs->ptr[0].panel_pnp_id.offset + panel_pnp_id_size != lfp_data_size)
> +		return false;
> +
> +	/* make sure the table entries have uniform size */
> +	for (i = 1; i < 16; i++) {
> +		if (ptrs->ptr[i].fp_timing.table_size != fp_timing_size ||
> +		    ptrs->ptr[i].dvo_timing.table_size != dvo_timing_size ||
> +		    ptrs->ptr[i].panel_pnp_id.table_size != panel_pnp_id_size)
> +			return false;
> +
> +		if (ptrs->ptr[i].fp_timing.offset - ptrs->ptr[i-1].fp_timing.offset != lfp_data_size ||
> +		    ptrs->ptr[i].dvo_timing.offset - ptrs->ptr[i-1].dvo_timing.offset != lfp_data_size ||
> +		    ptrs->ptr[i].panel_pnp_id.offset - ptrs->ptr[i-1].panel_pnp_id.offset != lfp_data_size)
> +			return false;
> +	}
> +
> +	/* make sure the tables fit inside the data block */
> +	for (i = 0; i < 16; i++) {
> +		if (ptrs->ptr[i].fp_timing.offset + fp_timing_size > data_block_size ||
> +		    ptrs->ptr[i].dvo_timing.offset + dvo_timing_size > data_block_size ||
> +		    ptrs->ptr[i].panel_pnp_id.offset + panel_pnp_id_size > data_block_size)
> +			return false;
> +	}
> +
> +	return true;
> +}
> +
>  /* make the data table offsets relative to the data block */
>  static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
>  {
> @@ -211,7 +291,7 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
>  		ptrs->ptr[i].panel_pnp_id.offset -= offset;
>  	}
>  
> -	return true;
> +	return validate_lfp_data_ptrs(bdb, ptrs);
>  }
>  
>  static void

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 05/22] drm/i915/bios: Trust the LFP data pointers
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 05/22] drm/i915/bios: Trust the LFP data pointers Ville Syrjala
@ 2022-04-07 16:12   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 16:12 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Now that we've sufficiently validated the LFP data pointers we
> can trust them.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 60 ++++++-----------------
>  1 file changed, 16 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index cd82ea4de8e1..925f521f1f84 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -397,44 +397,19 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
>  }
>  
>  static const struct lvds_dvo_timing *
> -get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,
> -		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs,
> +get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *data,
> +		    const struct bdb_lvds_lfp_data_ptrs *ptrs,
>  		    int index)
>  {
> -	/*
> -	 * the size of fp_timing varies on the different platform.
> -	 * So calculate the DVO timing relative offset in LVDS data
> -	 * entry to get the DVO timing entry
> -	 */
> -
> -	int lfp_data_size =
> -		lvds_lfp_data_ptrs->ptr[1].dvo_timing.offset -
> -		lvds_lfp_data_ptrs->ptr[0].dvo_timing.offset;
> -	int dvo_timing_offset =
> -		lvds_lfp_data_ptrs->ptr[0].dvo_timing.offset -
> -		lvds_lfp_data_ptrs->ptr[0].fp_timing.offset;
> -	char *entry = (char *)lvds_lfp_data->data + lfp_data_size * index;
> -
> -	return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);
> +	return (const void *)data + ptrs->ptr[index].dvo_timing.offset;
>  }
>  
> -/* get lvds_fp_timing entry
> - * this function may return NULL if the corresponding entry is invalid
> - */
>  static const struct lvds_fp_timing *
>  get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
>  		   const struct bdb_lvds_lfp_data_ptrs *ptrs,
>  		   int index)
>  {
> -	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */
> -	size_t ofs;
> -
> -	if (index >= ARRAY_SIZE(ptrs->ptr))
> -		return NULL;
> -	ofs = ptrs->ptr[index].fp_timing.offset;
> -	if (ofs + sizeof(struct lvds_fp_timing) > data_size)
> -		return NULL;
> -	return (const struct lvds_fp_timing *)((const u8 *)data + ofs);
> +	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
>  }
>  
>  /* Parse general panel options */
> @@ -499,8 +474,7 @@ parse_panel_options(struct drm_i915_private *i915)
>  
>  /* Try to find integrated panel timing data */
>  static void
> -parse_lfp_panel_dtd(struct drm_i915_private *i915,
> -		    const struct bdb_header *bdb)
> +parse_lfp_panel_dtd(struct drm_i915_private *i915)
>  {
>  	const struct bdb_lvds_lfp_data *lvds_lfp_data;
>  	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
> @@ -536,15 +510,14 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915,
>  	fp_timing = get_lvds_fp_timing(lvds_lfp_data,
>  				       lvds_lfp_data_ptrs,
>  				       panel_type);
> -	if (fp_timing) {
> -		/* check the resolution, just to be sure */
> -		if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
> -		    fp_timing->y_res == panel_fixed_mode->vdisplay) {
> -			i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
> -			drm_dbg_kms(&i915->drm,
> -				    "VBT initial LVDS value %x\n",
> -				    i915->vbt.bios_lvds_val);
> -		}
> +
> +	/* check the resolution, just to be sure */
> +	if (fp_timing->x_res == panel_fixed_mode->hdisplay &&
> +	    fp_timing->y_res == panel_fixed_mode->vdisplay) {
> +		i915->vbt.bios_lvds_val = fp_timing->lvds_reg_val;
> +		drm_dbg_kms(&i915->drm,
> +			    "VBT initial LVDS value %x\n",
> +			    i915->vbt.bios_lvds_val);
>  	}
>  }
>  
> @@ -627,8 +600,7 @@ parse_generic_dtd(struct drm_i915_private *i915)
>  }
>  
>  static void
> -parse_panel_dtd(struct drm_i915_private *i915,
> -		const struct bdb_header *bdb)
> +parse_panel_dtd(struct drm_i915_private *i915)
>  {
>  	/*
>  	 * Older VBTs provided provided DTD information for internal displays
> @@ -641,7 +613,7 @@ parse_panel_dtd(struct drm_i915_private *i915,
>  	if (i915->vbt.version >= 229)
>  		parse_generic_dtd(i915);
>  	if (!i915->vbt.lfp_lvds_vbt_mode)
> -		parse_lfp_panel_dtd(i915, bdb);
> +		parse_lfp_panel_dtd(i915);
>  }
>  
>  static void
> @@ -2720,7 +2692,7 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	parse_general_features(i915);
>  	parse_general_definitions(i915);
>  	parse_panel_options(i915);
> -	parse_panel_dtd(i915, bdb);
> +	parse_panel_dtd(i915);
>  	parse_lfp_backlight(i915);
>  	parse_sdvo_panel_data(i915);
>  	parse_driver_features(i915);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 06/22] drm/i915/bios: Validate the panel_name table
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 06/22] drm/i915/bios: Validate the panel_name table Ville Syrjala
@ 2022-04-07 16:14   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 16:14 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> In addition to the fp_timing,dvo_timing,panel_pnp_id tables
> there also exists a panel_name table. Unlike the others this
> is just one offset+table_size even though there are still 16
> actual panel_names in the data block.
>
> The panel_name table made its first appearance somewhere
> around VBT version 156-163. The exact version is not known.
> But we don't need to know that since we can just check whether
> the pointers block has enough room for it or not.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> ---
>  drivers/gpu/drm/i915/display/intel_bios.c     | 18 +++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_vbt_defs.h |  5 +++++
>  2 files changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 925f521f1f84..799c1fe36b23 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -206,7 +206,7 @@ static const struct {
>  static bool validate_lfp_data_ptrs(const void *bdb,
>  				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
>  {
> -	int fp_timing_size, dvo_timing_size, panel_pnp_id_size;
> +	int fp_timing_size, dvo_timing_size, panel_pnp_id_size, panel_name_size;
>  	int data_block_size, lfp_data_size;
>  	int i;
>  
> @@ -221,6 +221,7 @@ static bool validate_lfp_data_ptrs(const void *bdb,
>  	fp_timing_size = ptrs->ptr[0].fp_timing.table_size;
>  	dvo_timing_size = ptrs->ptr[0].dvo_timing.table_size;
>  	panel_pnp_id_size = ptrs->ptr[0].panel_pnp_id.table_size;
> +	panel_name_size = ptrs->panel_name.table_size;
>  
>  	/* fp_timing has variable size */
>  	if (fp_timing_size < 32 ||
> @@ -228,6 +229,11 @@ static bool validate_lfp_data_ptrs(const void *bdb,
>  	    panel_pnp_id_size != sizeof(struct lvds_pnp_id))
>  		return false;
>  
> +	/* panel_name is not present in old VBTs */
> +	if (panel_name_size != 0 &&
> +	    panel_name_size != sizeof(struct lvds_lfp_panel_name))
> +		return false;
> +
>  	lfp_data_size = ptrs->ptr[1].fp_timing.offset - ptrs->ptr[0].fp_timing.offset;
>  	if (16 * lfp_data_size > data_block_size)
>  		return false;
> @@ -268,6 +274,9 @@ static bool validate_lfp_data_ptrs(const void *bdb,
>  			return false;
>  	}
>  
> +	if (ptrs->panel_name.offset + 16 * panel_name_size > data_block_size)
> +		return false;
> +
>  	return true;
>  }
>  
> @@ -291,6 +300,13 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
>  		ptrs->ptr[i].panel_pnp_id.offset -= offset;
>  	}
>  
> +	if (ptrs->panel_name.table_size) {
> +		if (ptrs->panel_name.offset < offset)
> +			return false;
> +
> +		ptrs->panel_name.offset -= offset;
> +	}
> +
>  	return validate_lfp_data_ptrs(bdb, ptrs);
>  }
>  
> diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> index d727fcd6cdab..e4a11c3e3f3e 100644
> --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> @@ -737,6 +737,7 @@ struct lvds_lfp_data_ptr {
>  struct bdb_lvds_lfp_data_ptrs {
>  	u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */
>  	struct lvds_lfp_data_ptr ptr[16];
> +	struct lvds_lfp_data_ptr_table panel_name; /* 156-163? */
>  } __packed;
>  
>  /*
> @@ -778,6 +779,10 @@ struct bdb_lvds_lfp_data {
>  	struct lvds_lfp_data_entry data[16];
>  } __packed;
>  
> +struct lvds_lfp_panel_name {
> +	u8 name[13];
> +} __packed;
> +
>  /*
>   * Block 43 - LFP Backlight Control Data Block
>   */

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing Ville Syrjala
@ 2022-04-07 16:21   ` Jani Nikula
  2022-04-08 13:59     ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 16:21 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Reorder things so that we can parse the entier LFP data block

*entire

> in one go. For now we just stick to parsing the DTD from it.
>
> Also fix the misleading comment about block 42 being deprecated.
> Only the DTD part is deprecated, the rest is still very much needed.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 62 ++++++++++++-----------
>  1 file changed, 32 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 799c1fe36b23..f90991cac438 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -488,25 +488,16 @@ parse_panel_options(struct drm_i915_private *i915)
>  	}
>  }
>  
> -/* Try to find integrated panel timing data */
>  static void
> -parse_lfp_panel_dtd(struct drm_i915_private *i915)
> +parse_lfp_panel_dtd(struct drm_i915_private *i915,
> +		    const struct bdb_lvds_lfp_data *lvds_lfp_data,
> +		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs)
>  {
> -	const struct bdb_lvds_lfp_data *lvds_lfp_data;
> -	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
>  	const struct lvds_dvo_timing *panel_dvo_timing;
>  	const struct lvds_fp_timing *fp_timing;
>  	struct drm_display_mode *panel_fixed_mode;
>  	int panel_type = i915->vbt.panel_type;
>  
> -	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
> -	if (!lvds_lfp_data)
> -		return;
> -
> -	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> -	if (!lvds_lfp_data_ptrs)
> -		return;
> -
>  	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
>  					       lvds_lfp_data_ptrs,
>  					       panel_type);
> @@ -537,6 +528,24 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915)
>  	}
>  }
>  
> +static void
> +parse_lfp_data(struct drm_i915_private *i915)
> +{
> +	const struct bdb_lvds_lfp_data *data;
> +	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> +
> +	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> +	if (!ptrs)
> +		return;
> +
> +	data = find_section(i915, BDB_LVDS_LFP_DATA);
> +	if (!data)
> +		return;
> +
> +	if (!i915->vbt.lfp_lvds_vbt_mode)
> +		parse_lfp_panel_dtd(i915, data, ptrs);

Could do an early return on i915->vbt.lfp_lvds_vbt_mode.

> +}
> +
>  static void
>  parse_generic_dtd(struct drm_i915_private *i915)
>  {
> @@ -615,23 +624,6 @@ parse_generic_dtd(struct drm_i915_private *i915)
>  	i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
>  }
>  
> -static void
> -parse_panel_dtd(struct drm_i915_private *i915)
> -{
> -	/*
> -	 * Older VBTs provided provided DTD information for internal displays
> -	 * through the "LFP panel DTD" block (42).  As of VBT revision 229,
> -	 * that block is now deprecated and DTD information should be provided
> -	 * via a newer "generic DTD" block (58).  Just to be safe, we'll
> -	 * try the new generic DTD block first on VBT >= 229, but still fall
> -	 * back to trying the old LFP block if that fails.
> -	 */
> -	if (i915->vbt.version >= 229)
> -		parse_generic_dtd(i915);
> -	if (!i915->vbt.lfp_lvds_vbt_mode)
> -		parse_lfp_panel_dtd(i915);
> -}
> -
>  static void
>  parse_lfp_backlight(struct drm_i915_private *i915)
>  {
> @@ -2708,7 +2700,17 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	parse_general_features(i915);
>  	parse_general_definitions(i915);
>  	parse_panel_options(i915);
> -	parse_panel_dtd(i915);
> +	/*
> +	 * Older VBTs provided DTD information for internal displays through
> +	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
> +	 * DTD information should be provided via a newer "generic DTD"
> +	 * block (58).  Just to be safe, we'll try the new generic DTD block
> +	 * first on VBT >= 229, but still fall back to trying the old LFP
> +	 * block if that fails.
> +	 */
> +	if (i915->vbt.version >= 229)

I'd probably stick the vbt version check and the comment in
parse_generic_dtd() instead of polluting the top level.

Up to you if you want to do anything about the nitpicks,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +		parse_generic_dtd(i915);
> +	parse_lfp_data(i915);
>  	parse_lfp_backlight(i915);
>  	parse_sdvo_panel_data(i915);
>  	parse_driver_features(i915);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-06 13:39   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
  2022-04-07 12:24     ` Jani Nikula
@ 2022-04-07 16:53     ` Jani Nikula
  2022-04-07 18:18       ` Jani Nikula
  2022-04-12  8:19       ` Ville Syrjälä
  1 sibling, 2 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 16:53 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Modern VBTs no longer contain the LFP data table pointers
> block (41). We are expecting to have one in order to be able
> to parse the LFP data block (42), so let's make one up.
>
> Since the fp_timing table has variable size we must somehow
> determine its size. Rather than just hardcode it we look for
> the terminator bytes (0xffff) to figure out where each table
> entry starts. dvo_timing, panel_pnp_id, and panel_name are
> expected to have fixed size.
>
> This has been observed on various machines, eg. TGL with BDB
> version 240, CML with BDB version 231, etc. The most recent
> VBT I've observed that still had block 41 had BDB version
> 228. So presumably the cutoff (if an exact cutoff even exists)
> is somewhere around BDB version 229-231.
>
> v2: kfree the thing we allocated, not the thing+3 bytes
> v3: Do the debugprint only if we found the LFP data block
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 136 +++++++++++++++++++++-
>  1 file changed, 135 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 8b118c54314d..d32091dad1b0 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -310,16 +310,146 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
>  	return validate_lfp_data_ptrs(bdb, ptrs);
>  }
>  
> +static const void *find_fp_timing_terminator(const u8 *data, int size)
> +{
> +	int i;
> +
> +	if (!data)
> +		return NULL;
> +
> +	for (i = 0; i < size - 1; i++) {
> +		if (data[i] == 0xff && data[i+1] == 0xff)
> +			return &data[i];
> +	}
> +
> +	return NULL;
> +}
> +
> +static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
> +			     int table_size, int total_size)
> +{
> +	if (total_size < table_size)
> +		return total_size;
> +
> +	table->table_size = table_size;
> +	table->offset = total_size - table_size;
> +
> +	return total_size - table_size;
> +}
> +
> +static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
> +			      const struct lvds_lfp_data_ptr_table *prev,
> +			      int size)
> +{
> +	next->table_size = prev->table_size;
> +	next->offset = prev->offset + size;
> +}
> +
> +static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
> +				    const void *bdb)
> +{
> +	int i, size, table_size, block_size, offset;
> +	const void *t0, *t1, *block;
> +	struct bdb_lvds_lfp_data_ptrs *ptrs;
> +	void *ptrs_block;
> +
> +	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
> +	if (!block)
> +		return NULL;
> +
> +	drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
> +
> +	block_size = get_blocksize(block);
> +
> +	size = block_size;
> +	t0 = find_fp_timing_terminator(block, size);
> +
> +	size -= t0 - block - 2;
> +	t1 = find_fp_timing_terminator(t0 + 2, size);

Need to NULL check t0 before using it.

I'll still keep trying to wrap my head around the below stuff.

> +
> +	if (!t0 || !t1)
> +		return NULL;
> +
> +	size = t1 - t0;
> +	if (size * 16 > block_size)
> +		return NULL;
> +
> +	ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
> +	if (!ptrs_block)
> +		return NULL;
> +
> +	*(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS;
> +	*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
> +	ptrs = ptrs_block + 3;
> +
> +	table_size = sizeof(struct lvds_pnp_id);
> +	size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
> +
> +	table_size = sizeof(struct lvds_dvo_timing);
> +	size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
> +
> +	table_size = t0 - block + 2;
> +	size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
> +
> +	if (ptrs->ptr[0].fp_timing.table_size)
> +		ptrs->lvds_entries++;
> +	if (ptrs->ptr[0].dvo_timing.table_size)
> +		ptrs->lvds_entries++;
> +	if (ptrs->ptr[0].panel_pnp_id.table_size)
> +		ptrs->lvds_entries++;
> +
> +	if (size != 0 || ptrs->lvds_entries != 3) {
> +		kfree(ptrs);
> +		return NULL;
> +	}
> +
> +	size = t1 - t0;
> +	for (i = 1; i < 16; i++) {
> +		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
> +		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
> +		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
> +	}
> +
> +	size = t1 - t0;
> +	table_size = sizeof(struct lvds_lfp_panel_name);
> +
> +	if (16 * (size + table_size) <= block_size) {
> +		ptrs->panel_name.table_size = table_size;
> +		ptrs->panel_name.offset = size * 16;
> +	}
> +
> +	offset = block - bdb;
> +
> +	for (i = 0; i < 16; i++) {
> +		ptrs->ptr[i].fp_timing.offset += offset;
> +		ptrs->ptr[i].dvo_timing.offset += offset;
> +		ptrs->ptr[i].panel_pnp_id.offset += offset;
> +	}
> +
> +	if (ptrs->panel_name.table_size)
> +		ptrs->panel_name.offset += offset;
> +
> +	return ptrs_block;
> +}
> +
>  static void
>  init_bdb_block(struct drm_i915_private *i915,
>  	       const void *bdb, enum bdb_block_id section_id,
>  	       size_t min_size)
>  {
>  	struct bdb_block_entry *entry;
> +	void *temp_block = NULL;
>  	const void *block;
>  	size_t block_size;
>  
>  	block = find_raw_section(bdb, section_id);
> +
> +	/* Modern VBTs lack the LFP data table pointers block, make one up */
> +	if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) {
> +		temp_block = generate_lfp_data_ptrs(i915, bdb);
> +		if (temp_block)
> +			block = temp_block + 3;
> +	}
>  	if (!block)
>  		return;
>  
> @@ -330,12 +460,16 @@ init_bdb_block(struct drm_i915_private *i915,
>  
>  	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
>  			GFP_KERNEL);
> -	if (!entry)
> +	if (!entry) {
> +		kfree(temp_block);
>  		return;
> +	}
>  
>  	entry->section_id = section_id;
>  	memcpy(entry->data, block - 3, block_size + 3);
>  
> +	kfree(temp_block);
> +
>  	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
>  		    section_id, block_size, min_size);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 09/22] drm/i915/bios: Get access to the tail end of the LFP data block
  2022-04-06 13:40   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
@ 2022-04-07 17:07     ` Jani Nikula
  2022-04-08 14:04       ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:07 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We need to start parsing stuff from the tail end of the LFP data block.
> This is made awkward by the fact that the fp_timing table has variable
> size. So we must use a bit more finesse to get the tail end, and to
> make sure we allocate enough memory for it to make sure our struct
> representation fits.
>
> v2: Rebase due to the preallocation of BDB blocks
> v3: Rebase due to min_size WARN relocation
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c     | 39 ++++++++++++++++++-
>  drivers/gpu/drm/i915/display/intel_vbt_defs.h | 17 ++++++++
>  2 files changed, 55 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index d32091dad1b0..9a14d55b636c 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -188,7 +188,7 @@ static const struct {
>  	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
>  	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
>  	{ .section_id = BDB_LVDS_LFP_DATA,
> -	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
> +	  .min_size = 0, /* special case */ },
>  	{ .section_id = BDB_LVDS_BACKLIGHT,
>  	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
>  	{ .section_id = BDB_LFP_POWER,
> @@ -203,6 +203,23 @@ static const struct {
>  	  .min_size = sizeof(struct bdb_generic_dtd), },
>  };
>  
> +static size_t lfp_data_min_size(struct drm_i915_private *i915)
> +{
> +	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> +	size_t size;
> +
> +	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);

This depends on that block having been initialized before. Maybe the
ordering requirement deserves a comment in bdb_blocks[].

> +	if (!ptrs)
> +		return 0;
> +
> +	size = sizeof(struct bdb_lvds_lfp_data);

Basically that and the struct definition are bogus, though? They assume
a rigid structure. It might be true for some specific platforms, but
generally likely not.

Or we could of course just add a comment about that in intel_vbt_defs.h.

> +	if (ptrs->panel_name.table_size)
> +		size = max(size, ptrs->panel_name.offset +
> +			   sizeof(struct bdb_lvds_lfp_data_tail));
> +
> +	return size;
> +}
> +
>  static bool validate_lfp_data_ptrs(const void *bdb,
>  				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
>  {
> @@ -492,6 +509,9 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
>  		enum bdb_block_id section_id = bdb_blocks[i].section_id;
>  		size_t min_size = bdb_blocks[i].min_size;
>  
> +		if (section_id == BDB_LVDS_LFP_DATA)
> +			min_size = lfp_data_min_size(i915);

Nitpick, could also leave the "default" min size in bdb_blocks[], have
lfp_data_min_size() return the other value or 0, and have the max()
here. *shrug*

> +
>  		init_bdb_block(i915, bdb, section_id, min_size);
>  	}
>  }
> @@ -562,6 +582,16 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
>  	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
>  }
>  
> +static const struct bdb_lvds_lfp_data_tail *
> +get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
> +		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
> +{
> +	if (ptrs->panel_name.table_size)
> +		return (const void *)data + ptrs->panel_name.offset;
> +	else
> +		return NULL;
> +}
> +
>  /* Parse general panel options */
>  static void
>  parse_panel_options(struct drm_i915_private *i915)
> @@ -666,6 +696,7 @@ static void
>  parse_lfp_data(struct drm_i915_private *i915)
>  {
>  	const struct bdb_lvds_lfp_data *data;
> +	const struct bdb_lvds_lfp_data_tail *tail;
>  	const struct bdb_lvds_lfp_data_ptrs *ptrs;
>  
>  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> @@ -678,6 +709,12 @@ parse_lfp_data(struct drm_i915_private *i915)
>  
>  	if (!i915->vbt.lfp_lvds_vbt_mode)
>  		parse_lfp_panel_dtd(i915, data, ptrs);
> +
> +	tail = get_lfp_data_tail(data, ptrs);
> +	if (!tail)
> +		return;
> +
> +	(void)tail;

Mmmkay.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

>  }
>  
>  static void
> diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> index e4a11c3e3f3e..64551d206aeb 100644
> --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> @@ -783,6 +783,23 @@ struct lvds_lfp_panel_name {
>  	u8 name[13];
>  } __packed;
>  
> +struct lvds_lfp_black_border {
> +	u8 top; /*  227 */
> +	u8 bottom; /*  227 */
> +	u8 left; /* 238 */
> +	u8 right; /* 238 */
> +} __packed;
> +
> +struct bdb_lvds_lfp_data_tail {
> +	struct lvds_lfp_panel_name panel_name[16]; /* 156-163? */
> +	u16 scaling_enable; /* 187 */
> +	u8 seamless_drrs_min_refresh_rate[16]; /* 188 */
> +	u8 pixel_overlap_count[16]; /* 208 */
> +	struct lvds_lfp_black_border black_border[16]; /* 227 */
> +	u16 dual_lfp_port_sync_enable; /* 231 */
> +	u16 gpu_dithering_for_banding_artifacts; /* 245 */
> +} __packed;
> +
>  /*
>   * Block 43 - LFP Backlight Control Data Block
>   */

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 10/22] drm/i915/bios: Assume panel_type==0 if the VBT has bogus data
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 10/22] drm/i915/bios: Assume panel_type==0 if the VBT has bogus data Ville Syrjala
@ 2022-04-07 17:11   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:11 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Just assume panel_type==0 always if the VBT gives us bogus data.
> We actually already do this everywhere else except in
> parse_panel_options() since we just leave i915->vbt.panel_type
> zeroed. This also seems to be what Windows does.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 11 ++++++-----
>  1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 01e0b12e2dea..502d4c679198 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -613,13 +613,14 @@ parse_panel_options(struct drm_i915_private *i915)
>  	} else {
>  		if (lvds_options->panel_type > 0xf) {
>  			drm_dbg_kms(&i915->drm,
> -				    "Invalid VBT panel type 0x%x\n",
> +				    "Invalid VBT panel type 0x%x, assuming 0\n",
>  				    lvds_options->panel_type);
> -			return;
> +			panel_type = 0;
> +		} else {
> +			panel_type = lvds_options->panel_type;
> +			drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n",
> +				    panel_type);
>  		}
> -		panel_type = lvds_options->panel_type;
> -		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n",
> -			    panel_type);
>  	}
>  
>  	i915->vbt.panel_type = panel_type;

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 11/22] drm/i915/bios: Split parse_driver_features() into two parts
  2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 11/22] drm/i915/bios: Split parse_driver_features() into two parts Ville Syrjala
@ 2022-04-07 17:13   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:13 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> We use the "driver features" block for two different kinds
> of data: global data, and per panel data. Split the function
> into two parts along that line so that we can start doing the
> parsing in two different locations.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 502d4c679198..1a7f1aa79827 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -1097,6 +1097,16 @@ parse_driver_features(struct drm_i915_private *i915)
>  		    driver->lvds_config != BDB_DRIVER_FEATURE_INT_SDVO_LVDS)
>  			i915->vbt.int_lvds_support = 0;
>  	}
> +}
> +
> +static void
> +parse_panel_driver_features(struct drm_i915_private *i915)
> +{
> +	const struct bdb_driver_features *driver;
> +
> +	driver = find_section(i915, BDB_DRIVER_FEATURES);
> +	if (!driver)
> +		return;
>  
>  	if (i915->vbt.version < 228) {
>  		drm_dbg_kms(&i915->drm, "DRRS State Enabled:%d\n",
> @@ -2883,6 +2893,7 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	parse_lfp_backlight(i915);
>  	parse_sdvo_panel_data(i915);
>  	parse_driver_features(i915);
> +	parse_panel_driver_features(i915);
>  	parse_power_conservation_features(i915);
>  	parse_edp(i915);
>  	parse_psr(i915);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts Ville Syrjala
@ 2022-04-07 17:23   ` Jani Nikula
  2022-04-08 14:09     ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:23 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Parsing the panel specific data from VBT is currently happening
> too early. Split the whole thing into global vs. panel specific
> parts so that we can start doing the panel specific parsing at
> a later time.

Might want to mention panel_type here somewhere, that's basically the
split, right?

>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c    | 50 +++++++++++++-------
>  drivers/gpu/drm/i915/display/intel_bios.h    |  1 +
>  drivers/gpu/drm/i915/display/intel_display.c |  1 +
>  3 files changed, 35 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 1a7f1aa79827..da2b1932e10d 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -723,6 +723,9 @@ parse_generic_dtd(struct drm_i915_private *i915)
>  	struct drm_display_mode *panel_fixed_mode;
>  	int num_dtd;
>  
> +	if (i915->vbt.lfp_lvds_vbt_mode)
> +		return;
> +
>  	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
>  	if (!generic_dtd)
>  		return;
> @@ -891,6 +894,9 @@ parse_sdvo_panel_data(struct drm_i915_private *i915)
>  	struct drm_display_mode *panel_fixed_mode;
>  	int index;
>  
> +	if (i915->vbt.sdvo_lvds_vbt_mode)
> +		return;
> +
>  	index = i915->params.vbt_sdvo_panel_type;
>  	if (index == -2) {
>  		drm_dbg_kms(&i915->drm,
> @@ -1419,6 +1425,9 @@ parse_mipi_config(struct drm_i915_private *i915)
>  	int panel_type = i915->vbt.panel_type;
>  	enum port port;
>  
> +	if (i915->vbt.dsi.config)
> +		return;
> +
>  	/* parse MIPI blocks only if LFP type is MIPI */
>  	if (!intel_bios_is_dsi_present(i915, &port))
>  		return;
> @@ -1739,6 +1748,9 @@ parse_mipi_sequence(struct drm_i915_private *i915)
>  	u8 *data;
>  	int index = 0;
>  
> +	if (i915->vbt.dsi.data)
> +		return;
> +

All of the above checks to (presumably) allow calling
intel_bios_init_panel() multiple times feel a bit out of place here. At
the very least need a mention in the commit message.

Regardless,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


>  	/* Only our generic panel driver uses the sequence block. */
>  	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
>  		return;
> @@ -2878,6 +2890,27 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	/* Grab useful general definitions */
>  	parse_general_features(i915);
>  	parse_general_definitions(i915);
> +	parse_driver_features(i915);
> +
> +	/* Depends on child device list */
> +	parse_compression_parameters(i915);
> +
> +out:
> +	if (!vbt) {
> +		drm_info(&i915->drm,
> +			 "Failed to find VBIOS tables (VBT)\n");
> +		init_vbt_missing_defaults(i915);
> +	}
> +
> +	/* Further processing on pre-parsed or generated child device data */
> +	parse_sdvo_device_mapping(i915);
> +	parse_ddi_ports(i915);
> +
> +	kfree(oprom_vbt);
> +}
> +
> +void intel_bios_init_panel(struct drm_i915_private *i915)
> +{
>  	parse_panel_options(i915);
>  	/*
>  	 * Older VBTs provided DTD information for internal displays through
> @@ -2892,29 +2925,12 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	parse_lfp_data(i915);
>  	parse_lfp_backlight(i915);
>  	parse_sdvo_panel_data(i915);
> -	parse_driver_features(i915);
>  	parse_panel_driver_features(i915);
>  	parse_power_conservation_features(i915);
>  	parse_edp(i915);
>  	parse_psr(i915);
>  	parse_mipi_config(i915);
>  	parse_mipi_sequence(i915);
> -
> -	/* Depends on child device list */
> -	parse_compression_parameters(i915);
> -
> -out:
> -	if (!vbt) {
> -		drm_info(&i915->drm,
> -			 "Failed to find VBIOS tables (VBT)\n");
> -		init_vbt_missing_defaults(i915);
> -	}
> -
> -	/* Further processing on pre-parsed or generated child device data */
> -	parse_sdvo_device_mapping(i915);
> -	parse_ddi_ports(i915);
> -
> -	kfree(oprom_vbt);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> index 4709c4d29805..c744d75fa435 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.h
> +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> @@ -230,6 +230,7 @@ struct mipi_pps_data {
>  } __packed;
>  
>  void intel_bios_init(struct drm_i915_private *dev_priv);
> +void intel_bios_init_panel(struct drm_i915_private *dev_priv);
>  void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
>  bool intel_bios_is_valid_vbt(const void *buf, size_t size);
>  bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index eee185ed41c3..4ece4e7d0296 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -9650,6 +9650,7 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
>  	}
>  
>  	intel_bios_init(i915);
> +	intel_bios_init_panel(i915);
>  
>  	ret = intel_vga_register(i915);
>  	if (ret)

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 16/22] drm/i915/bios: Extract get_panel_type()
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 16/22] drm/i915/bios: Extract get_panel_type() Ville Syrjala
@ 2022-04-07 17:26   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:26 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Pull the code to determine the panel type into its own set of
> sane functions.
>
> v2: rebase
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 58 +++++++++++++++--------
>  1 file changed, 39 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index da2b1932e10d..26839263abf0 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -589,6 +589,44 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
>  		return NULL;
>  }
>  
> +static int vbt_panel_type(struct drm_i915_private *i915)
> +{
> +	const struct bdb_lvds_options *lvds_options;
> +
> +	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
> +	if (!lvds_options)
> +		return -1;
> +
> +	if (lvds_options->panel_type > 0xf) {
> +		drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n",
> +			    lvds_options->panel_type);
> +		return -1;
> +	}
> +
> +	return lvds_options->panel_type;
> +}
> +
> +static int get_panel_type(struct drm_i915_private *i915)
> +{
> +	int ret;
> +
> +	ret = intel_opregion_get_panel_type(i915);
> +	if (ret >= 0) {
> +		drm_WARN_ON(&i915->drm, ret > 0xf);
> +		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n", ret);
> +		return ret;
> +	}
> +
> +	ret = vbt_panel_type(i915);
> +	if (ret >= 0) {
> +		drm_WARN_ON(&i915->drm, ret > 0xf);
> +		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n", ret);
> +		return ret;
> +	}
> +
> +	return 0; /* fallback */
> +}
> +
>  /* Parse general panel options */
>  static void
>  parse_panel_options(struct drm_i915_private *i915)
> @@ -596,7 +634,6 @@ parse_panel_options(struct drm_i915_private *i915)
>  	const struct bdb_lvds_options *lvds_options;
>  	int panel_type;
>  	int drrs_mode;
> -	int ret;
>  
>  	lvds_options = find_section(i915, BDB_LVDS_OPTIONS);
>  	if (!lvds_options)
> @@ -604,24 +641,7 @@ parse_panel_options(struct drm_i915_private *i915)
>  
>  	i915->vbt.lvds_dither = lvds_options->pixel_dither;
>  
> -	ret = intel_opregion_get_panel_type(i915);
> -	if (ret >= 0) {
> -		drm_WARN_ON(&i915->drm, ret > 0xf);
> -		panel_type = ret;
> -		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n",
> -			    panel_type);
> -	} else {
> -		if (lvds_options->panel_type > 0xf) {
> -			drm_dbg_kms(&i915->drm,
> -				    "Invalid VBT panel type 0x%x, assuming 0\n",
> -				    lvds_options->panel_type);
> -			panel_type = 0;
> -		} else {
> -			panel_type = lvds_options->panel_type;
> -			drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n",
> -				    panel_type);
> -		}
> -	}
> +	panel_type = get_panel_type(i915);
>  
>  	i915->vbt.panel_type = panel_type;

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code Ville Syrjala
@ 2022-04-07 17:49   ` Jani Nikula
  2022-04-08 14:13     ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:49 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make the panel type code a bit more abstract along the
> lines of the source of the panel type. For the moment
> we have three classes: OpRegion, VBT, fallback.
> Well introduce another one shortly.
>
> We can now also print out all the different panel types,
> and indicate which one we ultimately selected. Could help
> with debugging.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 47 ++++++++++++++++-------
>  1 file changed, 34 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 26839263abf0..feef5aa97398 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -606,25 +606,46 @@ static int vbt_panel_type(struct drm_i915_private *i915)
>  	return lvds_options->panel_type;
>  }
>  
> +enum panel_type {
> +	PANEL_TYPE_OPREGION,
> +	PANEL_TYPE_VBT,
> +	PANEL_TYPE_FALLBACK,
> +};
> +
>  static int get_panel_type(struct drm_i915_private *i915)
>  {
> -	int ret;
> +	struct {
> +		const char *name;
> +		int panel_type;
> +	} panel_types[] = {
> +		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
> +		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
> +		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
> +	};
> +	int i;
>  
> -	ret = intel_opregion_get_panel_type(i915);
> -	if (ret >= 0) {
> -		drm_WARN_ON(&i915->drm, ret > 0xf);
> -		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n", ret);
> -		return ret;
> -	}
> +	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
> +	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);

I'd probably add a function pointer in the array, to be able to call
these nicely in the loop. Needs a static wrapper function for
intel_opregion_get_panel_type() in the follow-up to eat the edid
parameter, but I think it's worth it.

> +
> +	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
> +		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);

I know that's loud, but it's kind of annoying that the out of bounds
value still goes through here.

>  
> -	ret = vbt_panel_type(i915);
> -	if (ret >= 0) {
> -		drm_WARN_ON(&i915->drm, ret > 0xf);
> -		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n", ret);
> -		return ret;
> +		if (panel_types[i].panel_type >= 0)
> +			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
> +				    panel_types[i].name, panel_types[i].panel_type);
>  	}
>  
> -	return 0; /* fallback */
> +	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
> +		i = PANEL_TYPE_OPREGION;
> +	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
> +		i = PANEL_TYPE_VBT;
> +	else
> +		i = PANEL_TYPE_FALLBACK;

At this stage, we could set this in the loop too, but dunno how
complicated that gets with the pnpid match rules.

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> +
> +	drm_dbg_kms(&i915->drm, "Selected panel type (%s): %d\n",
> +		    panel_types[i].name, panel_types[i].panel_type);
> +
> +	return panel_types[i].panel_type;
>  }
>  
>  /* Parse general panel options */

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v4 18/22] drm/i915/bios: Determine panel type via PNPID match
  2022-04-06 19:09   ` [Intel-gfx] [PATCH v4 " Ville Syrjala
@ 2022-04-07 17:55     ` Jani Nikula
  2022-04-08 14:51       ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:55 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Apparently when the VBT panel_type==0xff we should trawl through
> the PNPID table and check for a match against the EDID. If a
> match is found the index gives us the panel_type.
>
> Tried to match the Windows behaviour here with first looking
> for an exact match, and if one isn't found we fall back to
> looking for a match w/o the mfg year/week.

Does Windows also probe the EDID first, or does it use some side channel
to use the GOP probed EDID? ISTR there's something in the EFI interface
for this, but never looked deeper.

>
> v2: Rebase due to vlv_dsi changes
>
> Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5545
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  drivers/gpu/drm/i915/display/icl_dsi.c    |  2 +-
>  drivers/gpu/drm/i915/display/intel_bios.c | 82 ++++++++++++++++++++---
>  drivers/gpu/drm/i915/display/intel_bios.h |  4 +-
>  drivers/gpu/drm/i915/display/intel_dp.c   |  2 +-
>  drivers/gpu/drm/i915/display/intel_lvds.c |  2 +-
>  drivers/gpu/drm/i915/display/intel_sdvo.c |  2 +-
>  drivers/gpu/drm/i915/display/vlv_dsi.c    |  2 +-
>  7 files changed, 82 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
> index 688176d4a54a..49715485a3a6 100644
> --- a/drivers/gpu/drm/i915/display/icl_dsi.c
> +++ b/drivers/gpu/drm/i915/display/icl_dsi.c
> @@ -2048,7 +2048,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
>  	/* attach connector to encoder */
>  	intel_connector_attach_encoder(intel_connector, encoder);
>  
> -	intel_bios_init_panel(dev_priv);
> +	intel_bios_init_panel(dev_priv, NULL);
>  
>  	mutex_lock(&dev->mode_config.mutex);
>  	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index 0e76c554581a..4c0680356134 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -582,6 +582,14 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
>  	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
>  }
>  
> +static const struct lvds_pnp_id *
> +get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data,
> +		const struct bdb_lvds_lfp_data_ptrs *ptrs,
> +		int index)
> +{
> +	return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset;
> +}
> +
>  static const struct bdb_lvds_lfp_data_tail *
>  get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
>  		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
> @@ -592,6 +600,52 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
>  		return NULL;
>  }
>  
> +static int pnp_id_panel_type(struct drm_i915_private *i915,
> +			     const struct edid *edid)
> +{
> +	const struct bdb_lvds_lfp_data *data;
> +	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> +	const struct lvds_pnp_id *edid_id;
> +	struct lvds_pnp_id edid_id_nodate;
> +	int i, best = -1;
> +
> +	if (!edid)
> +		return -1;
> +
> +	edid_id = (const void *)&edid->mfg_id[0];
> +
> +	edid_id_nodate = *edid_id;
> +	edid_id_nodate.mfg_week = 0;
> +	edid_id_nodate.mfg_year = 0;
> +
> +	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> +	if (!ptrs)
> +		return -1;
> +
> +	data = find_section(i915, BDB_LVDS_LFP_DATA);
> +	if (!data)
> +		return -1;
> +
> +	for (i = 0; i < 16; i++) {
> +		const struct lvds_pnp_id *vbt_id =
> +			get_lvds_pnp_id(data, ptrs, i);
> +
> +		/* full match? */
> +		if (!memcmp(vbt_id, edid_id, sizeof(*vbt_id)))
> +			return i;
> +
> +		/*
> +		 * Accept a match w/o date if no full match is found,
> +		 * and the VBT entry does not specify a date.
> +		 */
> +		if (best < 0 &&
> +		    !memcmp(vbt_id, &edid_id_nodate, sizeof(*vbt_id)))
> +			best = i;
> +	}
> +
> +	return best;
> +}
> +
>  static int vbt_panel_type(struct drm_i915_private *i915)
>  {
>  	const struct bdb_lvds_options *lvds_options;
> @@ -600,7 +654,8 @@ static int vbt_panel_type(struct drm_i915_private *i915)
>  	if (!lvds_options)
>  		return -1;
>  
> -	if (lvds_options->panel_type > 0xf) {
> +	if (lvds_options->panel_type > 0xf &&
> +	    lvds_options->panel_type != 0xff) {
>  		drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n",
>  			    lvds_options->panel_type);
>  		return -1;
> @@ -612,10 +667,12 @@ static int vbt_panel_type(struct drm_i915_private *i915)
>  enum panel_type {
>  	PANEL_TYPE_OPREGION,
>  	PANEL_TYPE_VBT,
> +	PANEL_TYPE_PNPID,
>  	PANEL_TYPE_FALLBACK,
>  };
>  
> -static int get_panel_type(struct drm_i915_private *i915)
> +static int get_panel_type(struct drm_i915_private *i915,
> +			  const struct edid *edid)
>  {
>  	struct {
>  		const char *name;
> @@ -623,15 +680,18 @@ static int get_panel_type(struct drm_i915_private *i915)
>  	} panel_types[] = {
>  		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
>  		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
> +		[PANEL_TYPE_PNPID] = { .name = "PNPID", .panel_type = -1, },
>  		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
>  	};
>  	int i;
>  
>  	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
>  	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);
> +	panel_types[PANEL_TYPE_PNPID].panel_type = pnp_id_panel_type(i915, edid);
>  
>  	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
> -		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);
> +		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf &&
> +			    panel_types[i].panel_type != 0xff);
>  
>  		if (panel_types[i].panel_type >= 0)
>  			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
> @@ -640,7 +700,11 @@ static int get_panel_type(struct drm_i915_private *i915)
>  
>  	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
>  		i = PANEL_TYPE_OPREGION;
> -	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
> +	else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
> +		 panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
> +		i = PANEL_TYPE_PNPID;
> +	else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
> +		 panel_types[PANEL_TYPE_VBT].panel_type >= 0)
>  		i = PANEL_TYPE_VBT;
>  	else
>  		i = PANEL_TYPE_FALLBACK;
> @@ -653,7 +717,8 @@ static int get_panel_type(struct drm_i915_private *i915)
>  
>  /* Parse general panel options */
>  static void
> -parse_panel_options(struct drm_i915_private *i915)
> +parse_panel_options(struct drm_i915_private *i915,
> +		    const struct edid *edid)
>  {
>  	const struct bdb_lvds_options *lvds_options;
>  	int panel_type;
> @@ -665,7 +730,7 @@ parse_panel_options(struct drm_i915_private *i915)
>  
>  	i915->vbt.lvds_dither = lvds_options->pixel_dither;
>  
> -	panel_type = get_panel_type(i915);
> +	panel_type = get_panel_type(i915, edid);
>  
>  	i915->vbt.panel_type = panel_type;
>  
> @@ -2953,9 +3018,10 @@ void intel_bios_init(struct drm_i915_private *i915)
>  	kfree(oprom_vbt);
>  }
>  
> -void intel_bios_init_panel(struct drm_i915_private *i915)
> +void intel_bios_init_panel(struct drm_i915_private *i915,
> +			   const struct edid *edid)
>  {
> -	parse_panel_options(i915);
> +	parse_panel_options(i915, edid);
>  	/*
>  	 * Older VBTs provided DTD information for internal displays through
>  	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> index c744d75fa435..be6d57bd0f5a 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.h
> +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> @@ -33,6 +33,7 @@
>  #include <linux/types.h>
>  
>  struct drm_i915_private;
> +struct edid;
>  struct intel_bios_encoder_data;
>  struct intel_crtc_state;
>  struct intel_encoder;
> @@ -230,7 +231,8 @@ struct mipi_pps_data {
>  } __packed;
>  
>  void intel_bios_init(struct drm_i915_private *dev_priv);
> -void intel_bios_init_panel(struct drm_i915_private *dev_priv);
> +void intel_bios_init_panel(struct drm_i915_private *dev_priv,
> +			   const struct edid *edid);
>  void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
>  bool intel_bios_is_valid_vbt(const void *buf, size_t size);
>  bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index a1b5d7f5388b..41ac55a700e9 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -5179,7 +5179,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	}
>  	intel_connector->edid = edid;
>  
> -	intel_bios_init_panel(dev_priv);
> +	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
>  
>  	intel_panel_add_edid_fixed_modes(intel_connector,
>  					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
> diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
> index 554badf041f2..660bb95f2bf7 100644
> --- a/drivers/gpu/drm/i915/display/intel_lvds.c
> +++ b/drivers/gpu/drm/i915/display/intel_lvds.c
> @@ -967,7 +967,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
>  	}
>  	intel_connector->edid = edid;
>  
> -	intel_bios_init_panel(dev_priv);
> +	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
>  
>  	/* Try EDID first */
>  	intel_panel_add_edid_fixed_modes(intel_connector,
> diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> index 661a1057a073..25195bc1edca 100644
> --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> @@ -2900,7 +2900,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
>  	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
>  		goto err;
>  
> -	intel_bios_init_panel(i915);
> +	intel_bios_init_panel(i915, NULL);
>  
>  	/*
>  	 * Fetch modes from VBT. For SDVO prefer the VBT mode since some
> diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
> index 08fb554ff7ad..1af6e927af9b 100644
> --- a/drivers/gpu/drm/i915/display/vlv_dsi.c
> +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
> @@ -1929,7 +1929,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
>  	else
>  		intel_dsi->ports = BIT(port);
>  
> -	intel_bios_init_panel(dev_priv);
> +	intel_bios_init_panel(dev_priv, NULL);
>  
>  	intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports;
>  	intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports;

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 19/22] drm/i915/bios: Parse the seamless DRRS min refresh rate
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 19/22] drm/i915/bios: Parse the seamless DRRS min refresh rate Ville Syrjala
@ 2022-04-07 17:56   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 17:56 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Extract the seamless DRRS min refresh rate from the VBT.
>
> v2: Do a version check
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 9 ++++++++-
>  drivers/gpu/drm/i915/i915_drv.h           | 1 +
>  2 files changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index cfdfe91d4ccf..d561551d6324 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -802,6 +802,7 @@ parse_lfp_data(struct drm_i915_private *i915)
>  	const struct bdb_lvds_lfp_data *data;
>  	const struct bdb_lvds_lfp_data_tail *tail;
>  	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> +	int panel_type = i915->vbt.panel_type;
>  
>  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
>  	if (!ptrs)
> @@ -818,7 +819,13 @@ parse_lfp_data(struct drm_i915_private *i915)
>  	if (!tail)
>  		return;
>  
> -	(void)tail;
> +	if (i915->vbt.version >= 188) {
> +		i915->vbt.seamless_drrs_min_refresh_rate =
> +			tail->seamless_drrs_min_refresh_rate[panel_type];
> +		drm_dbg_kms(&i915->drm,
> +			    "Seamless DRRS min refresh rate: %d Hz\n",
> +			    i915->vbt.seamless_drrs_min_refresh_rate);
> +	}
>  }
>  
>  static void
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 9274417cd87a..7b6858651420 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -327,6 +327,7 @@ struct intel_vbt_data {
>  	bool override_afc_startup;
>  	u8 override_afc_startup_val;
>  
> +	u8 seamless_drrs_min_refresh_rate;
>  	enum drrs_type drrs_type;
>  
>  	struct {

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 20/22] drm/i915: Respect VBT seamless DRRS min refresh rate
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 20/22] drm/i915: Respect VBT " Ville Syrjala
@ 2022-04-07 18:01   ` Jani Nikula
  0 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 18:01 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make sure our choice of downclock mode respects the VBT
> seameless DRRS min refresh rate limit.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_panel.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
> index 03398feb6676..35d8676438a3 100644
> --- a/drivers/gpu/drm/i915/display/intel_panel.c
> +++ b/drivers/gpu/drm/i915/display/intel_panel.c
> @@ -75,13 +75,17 @@ const struct drm_display_mode *
>  intel_panel_downclock_mode(struct intel_connector *connector,
>  			   const struct drm_display_mode *adjusted_mode)
>  {
> +	struct drm_i915_private *i915 = to_i915(connector->base.dev);
>  	const struct drm_display_mode *fixed_mode, *best_mode = NULL;
> -	int vrefresh = drm_mode_vrefresh(adjusted_mode);
> +	int min_vrefresh = i915->vbt.seamless_drrs_min_refresh_rate;

Just remembered the rabbit hole goes deeper with dual eDP and supporting
multiple copies of all the panel type specific stuff... ;)

> +	int max_vrefresh = drm_mode_vrefresh(adjusted_mode);
>  
>  	/* pick the fixed_mode with the lowest refresh rate */
>  	list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) {
> -		if (drm_mode_vrefresh(fixed_mode) < vrefresh) {
> -			vrefresh = drm_mode_vrefresh(fixed_mode);
> +		int vrefesh = drm_mode_vrefresh(fixed_mode);

*vrefresh

Reviewed-by: Jani Nikula <jani.nikula@intel.com>


> +
> +		if (vrefesh >= min_vrefresh && vrefesh < max_vrefresh) {
> +			max_vrefresh = vrefesh;
>  			best_mode = fixed_mode;
>  		}
>  	}

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 21/22] drm/edid: Extract drm_edid_decode_mfg_id()
  2022-04-05 17:34   ` [Intel-gfx] " Ville Syrjala
  (?)
@ 2022-04-07 18:02   ` Jani Nikula
  -1 siblings, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 18:02 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx; +Cc: dri-devel

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Make the PNPID decoding available for other users.
>
> Cc: dri-devel@lists.freedesktop.org
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> ---
>  include/drm/drm_edid.h | 21 +++++++++++++++++----
>  1 file changed, 17 insertions(+), 4 deletions(-)
>
> diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
> index b7e170584000..5e9d7fcda8e7 100644
> --- a/include/drm/drm_edid.h
> +++ b/include/drm/drm_edid.h
> @@ -508,6 +508,22 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
>  	return eld[DRM_ELD_SAD_COUNT_CONN_TYPE] & DRM_ELD_CONN_TYPE_MASK;
>  }
>  
> +/**
> + * drm_edid_decode_mfg_id - Decode the manufacturer ID
> + * @mfg_id: The manufacturer ID
> + * @vend: A 4-byte buffer to store the 3-letter vendor string plus a '\0'
> + *	  termination
> + */
> +static inline const char *drm_edid_decode_mfg_id(u16 mfg_id, char vend[4])
> +{
> +	vend[0] = '@' + ((mfg_id >> 10) & 0x1f);
> +	vend[1] = '@' + ((mfg_id >> 5) & 0x1f);
> +	vend[2] = '@' + ((mfg_id >> 0) & 0x1f);
> +	vend[3] = '\0';
> +
> +	return vend;
> +}
> +
>  /**
>   * drm_edid_encode_panel_id - Encode an ID for matching against drm_edid_get_panel_id()
>   * @vend_chr_0: First character of the vendor string.
> @@ -548,10 +564,7 @@ static inline u8 drm_eld_get_conn_type(const uint8_t *eld)
>  static inline void drm_edid_decode_panel_id(u32 panel_id, char vend[4], u16 *product_id)
>  {
>  	*product_id = (u16)(panel_id & 0xffff);
> -	vend[0] = '@' + ((panel_id >> 26) & 0x1f);
> -	vend[1] = '@' + ((panel_id >> 21) & 0x1f);
> -	vend[2] = '@' + ((panel_id >> 16) & 0x1f);
> -	vend[3] = '\0';
> +	drm_edid_decode_mfg_id(panel_id >> 16, vend);
>  }
>  
>  bool drm_probe_ddc(struct i2c_adapter *adapter);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 22/22] drm/i915/bios: Dump PNPID and panel name
  2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 22/22] drm/i915/bios: Dump PNPID and panel name Ville Syrjala
@ 2022-04-07 18:07   ` Jani Nikula
  2022-04-08 14:52     ` Ville Syrjälä
  0 siblings, 1 reply; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 18:07 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Dump the panel PNPID and name from the VBT.
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_bios.c | 24 +++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> index d561551d6324..953526a7dc5d 100644
> --- a/drivers/gpu/drm/i915/display/intel_bios.c
> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> @@ -25,6 +25,7 @@
>   *
>   */
>  
> +#include <drm/drm_edid.h>
>  #include <drm/dp/drm_dp_helper.h>
>  
>  #include "display/intel_display.h"
> @@ -597,6 +598,19 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
>  		return NULL;
>  }
>  
> +static void dump_pnp_id(struct drm_i915_private *i915,
> +			const struct lvds_pnp_id *pnp_id,
> +			const char *name)
> +{
> +	u16 mfg_name = be16_to_cpu((__force __be16)pnp_id->mfg_name);

Might just add the __be16 in the struct member?

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

> +	char vend[4];
> +
> +	drm_dbg_kms(&i915->drm, "%s PNPID mfg: %s (0x%x), prod: %u, serial: %u, week: %d, year: %d\n",
> +		    name, drm_edid_decode_mfg_id(mfg_name, vend),
> +		    pnp_id->mfg_name, pnp_id->product_code, pnp_id->serial,
> +		    pnp_id->mfg_week, pnp_id->mfg_year + 1990);
> +}
> +
>  static int pnp_id_panel_type(struct drm_i915_private *i915,
>  			     const struct edid *edid)
>  {
> @@ -615,6 +629,8 @@ static int pnp_id_panel_type(struct drm_i915_private *i915,
>  	edid_id_nodate.mfg_week = 0;
>  	edid_id_nodate.mfg_year = 0;
>  
> +	dump_pnp_id(i915, edid_id, "EDID");
> +
>  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
>  	if (!ptrs)
>  		return -1;
> @@ -802,6 +818,7 @@ parse_lfp_data(struct drm_i915_private *i915)
>  	const struct bdb_lvds_lfp_data *data;
>  	const struct bdb_lvds_lfp_data_tail *tail;
>  	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> +	const struct lvds_pnp_id *pnp_id;
>  	int panel_type = i915->vbt.panel_type;
>  
>  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> @@ -815,10 +832,17 @@ parse_lfp_data(struct drm_i915_private *i915)
>  	if (!i915->vbt.lfp_lvds_vbt_mode)
>  		parse_lfp_panel_dtd(i915, data, ptrs);
>  
> +	pnp_id = get_lvds_pnp_id(data, ptrs, panel_type);
> +	dump_pnp_id(i915, pnp_id, "Panel");
> +
>  	tail = get_lfp_data_tail(data, ptrs);
>  	if (!tail)
>  		return;
>  
> +	drm_dbg_kms(&i915->drm, "Panel name: %.*s\n",
> +		    (int)sizeof(tail->panel_name[0].name),
> +		    tail->panel_name[panel_type].name);
> +
>  	if (i915->vbt.version >= 188) {
>  		i915->vbt.seamless_drrs_min_refresh_rate =
>  			tail->seamless_drrs_min_refresh_rate[panel_type];

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-07 16:53     ` Jani Nikula
@ 2022-04-07 18:18       ` Jani Nikula
  2022-04-12  8:19       ` Ville Syrjälä
  1 sibling, 0 replies; 72+ messages in thread
From: Jani Nikula @ 2022-04-07 18:18 UTC (permalink / raw)
  To: Ville Syrjala, intel-gfx

On Thu, 07 Apr 2022, Jani Nikula <jani.nikula@linux.intel.com> wrote:
> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>
>> Modern VBTs no longer contain the LFP data table pointers
>> block (41). We are expecting to have one in order to be able
>> to parse the LFP data block (42), so let's make one up.
>>
>> Since the fp_timing table has variable size we must somehow
>> determine its size. Rather than just hardcode it we look for
>> the terminator bytes (0xffff) to figure out where each table
>> entry starts. dvo_timing, panel_pnp_id, and panel_name are
>> expected to have fixed size.
>>
>> This has been observed on various machines, eg. TGL with BDB
>> version 240, CML with BDB version 231, etc. The most recent
>> VBT I've observed that still had block 41 had BDB version
>> 228. So presumably the cutoff (if an exact cutoff even exists)
>> is somewhere around BDB version 229-231.
>>
>> v2: kfree the thing we allocated, not the thing+3 bytes
>> v3: Do the debugprint only if we found the LFP data block
>>
>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> ---
>>  drivers/gpu/drm/i915/display/intel_bios.c | 136 +++++++++++++++++++++-
>>  1 file changed, 135 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
>> index 8b118c54314d..d32091dad1b0 100644
>> --- a/drivers/gpu/drm/i915/display/intel_bios.c
>> +++ b/drivers/gpu/drm/i915/display/intel_bios.c
>> @@ -310,16 +310,146 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
>>  	return validate_lfp_data_ptrs(bdb, ptrs);
>>  }
>>  
>> +static const void *find_fp_timing_terminator(const u8 *data, int size)
>> +{
>> +	int i;
>> +
>> +	if (!data)
>> +		return NULL;
>> +
>> +	for (i = 0; i < size - 1; i++) {
>> +		if (data[i] == 0xff && data[i+1] == 0xff)
>> +			return &data[i];
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
>> +			     int table_size, int total_size)
>> +{
>> +	if (total_size < table_size)
>> +		return total_size;
>> +
>> +	table->table_size = table_size;
>> +	table->offset = total_size - table_size;
>> +
>> +	return total_size - table_size;
>> +}
>> +
>> +static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
>> +			      const struct lvds_lfp_data_ptr_table *prev,
>> +			      int size)
>> +{
>> +	next->table_size = prev->table_size;
>> +	next->offset = prev->offset + size;
>> +}
>> +
>> +static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
>> +				    const void *bdb)
>> +{
>> +	int i, size, table_size, block_size, offset;
>> +	const void *t0, *t1, *block;
>> +	struct bdb_lvds_lfp_data_ptrs *ptrs;
>> +	void *ptrs_block;
>> +
>> +	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
>> +	if (!block)
>> +		return NULL;
>> +
>> +	drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
>> +
>> +	block_size = get_blocksize(block);
>> +
>> +	size = block_size;
>> +	t0 = find_fp_timing_terminator(block, size);
>> +
>> +	size -= t0 - block - 2;
>> +	t1 = find_fp_timing_terminator(t0 + 2, size);
>
> Need to NULL check t0 before using it.
>
> I'll still keep trying to wrap my head around the below stuff.

I guess I'll try again tomorrow with fresh eyes, but I have a hard time
following what's going on here. x_X

BR,
Jani.

>
>> +
>> +	if (!t0 || !t1)
>> +		return NULL;
>> +
>> +	size = t1 - t0;
>> +	if (size * 16 > block_size)
>> +		return NULL;
>> +
>> +	ptrs_block = kzalloc(sizeof(*ptrs) + 3, GFP_KERNEL);
>> +	if (!ptrs_block)
>> +		return NULL;
>> +
>> +	*(u8 *)(ptrs_block + 0) = BDB_LVDS_LFP_DATA_PTRS;
>> +	*(u16 *)(ptrs_block + 1) = sizeof(*ptrs);
>> +	ptrs = ptrs_block + 3;
>> +
>> +	table_size = sizeof(struct lvds_pnp_id);
>> +	size = make_lfp_data_ptr(&ptrs->ptr[0].panel_pnp_id, table_size, size);
>> +
>> +	table_size = sizeof(struct lvds_dvo_timing);
>> +	size = make_lfp_data_ptr(&ptrs->ptr[0].dvo_timing, table_size, size);
>> +
>> +	table_size = t0 - block + 2;
>> +	size = make_lfp_data_ptr(&ptrs->ptr[0].fp_timing, table_size, size);
>> +
>> +	if (ptrs->ptr[0].fp_timing.table_size)
>> +		ptrs->lvds_entries++;
>> +	if (ptrs->ptr[0].dvo_timing.table_size)
>> +		ptrs->lvds_entries++;
>> +	if (ptrs->ptr[0].panel_pnp_id.table_size)
>> +		ptrs->lvds_entries++;
>> +
>> +	if (size != 0 || ptrs->lvds_entries != 3) {
>> +		kfree(ptrs);
>> +		return NULL;
>> +	}
>> +
>> +	size = t1 - t0;
>> +	for (i = 1; i < 16; i++) {
>> +		next_lfp_data_ptr(&ptrs->ptr[i].fp_timing, &ptrs->ptr[i-1].fp_timing, size);
>> +		next_lfp_data_ptr(&ptrs->ptr[i].dvo_timing, &ptrs->ptr[i-1].dvo_timing, size);
>> +		next_lfp_data_ptr(&ptrs->ptr[i].panel_pnp_id, &ptrs->ptr[i-1].panel_pnp_id, size);
>> +	}
>> +
>> +	size = t1 - t0;
>> +	table_size = sizeof(struct lvds_lfp_panel_name);
>> +
>> +	if (16 * (size + table_size) <= block_size) {
>> +		ptrs->panel_name.table_size = table_size;
>> +		ptrs->panel_name.offset = size * 16;
>> +	}
>> +
>> +	offset = block - bdb;
>> +
>> +	for (i = 0; i < 16; i++) {
>> +		ptrs->ptr[i].fp_timing.offset += offset;
>> +		ptrs->ptr[i].dvo_timing.offset += offset;
>> +		ptrs->ptr[i].panel_pnp_id.offset += offset;
>> +	}
>> +
>> +	if (ptrs->panel_name.table_size)
>> +		ptrs->panel_name.offset += offset;
>> +
>> +	return ptrs_block;
>> +}
>> +
>>  static void
>>  init_bdb_block(struct drm_i915_private *i915,
>>  	       const void *bdb, enum bdb_block_id section_id,
>>  	       size_t min_size)
>>  {
>>  	struct bdb_block_entry *entry;
>> +	void *temp_block = NULL;
>>  	const void *block;
>>  	size_t block_size;
>>  
>>  	block = find_raw_section(bdb, section_id);
>> +
>> +	/* Modern VBTs lack the LFP data table pointers block, make one up */
>> +	if (!block && section_id == BDB_LVDS_LFP_DATA_PTRS) {
>> +		temp_block = generate_lfp_data_ptrs(i915, bdb);
>> +		if (temp_block)
>> +			block = temp_block + 3;
>> +	}
>>  	if (!block)
>>  		return;
>>  
>> @@ -330,12 +460,16 @@ init_bdb_block(struct drm_i915_private *i915,
>>  
>>  	entry = kzalloc(struct_size(entry, data, max(min_size, block_size) + 3),
>>  			GFP_KERNEL);
>> -	if (!entry)
>> +	if (!entry) {
>> +		kfree(temp_block);
>>  		return;
>> +	}
>>  
>>  	entry->section_id = section_id;
>>  	memcpy(entry->data, block - 3, block_size + 3);
>>  
>> +	kfree(temp_block);
>> +
>>  	drm_dbg_kms(&i915->drm, "Found BDB block %d (size %zu, min size %zu)\n",
>>  		    section_id, block_size, min_size);

-- 
Jani Nikula, Intel Open Source Graphics Center

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing
  2022-04-07 16:21   ` Jani Nikula
@ 2022-04-08 13:59     ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-08 13:59 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 07:21:44PM +0300, Jani Nikula wrote:
> On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Reorder things so that we can parse the entier LFP data block
> 
> *entire
> 
> > in one go. For now we just stick to parsing the DTD from it.
> >
> > Also fix the misleading comment about block 42 being deprecated.
> > Only the DTD part is deprecated, the rest is still very much needed.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c | 62 ++++++++++++-----------
> >  1 file changed, 32 insertions(+), 30 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 799c1fe36b23..f90991cac438 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -488,25 +488,16 @@ parse_panel_options(struct drm_i915_private *i915)
> >  	}
> >  }
> >  
> > -/* Try to find integrated panel timing data */
> >  static void
> > -parse_lfp_panel_dtd(struct drm_i915_private *i915)
> > +parse_lfp_panel_dtd(struct drm_i915_private *i915,
> > +		    const struct bdb_lvds_lfp_data *lvds_lfp_data,
> > +		    const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs)
> >  {
> > -	const struct bdb_lvds_lfp_data *lvds_lfp_data;
> > -	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
> >  	const struct lvds_dvo_timing *panel_dvo_timing;
> >  	const struct lvds_fp_timing *fp_timing;
> >  	struct drm_display_mode *panel_fixed_mode;
> >  	int panel_type = i915->vbt.panel_type;
> >  
> > -	lvds_lfp_data = find_section(i915, BDB_LVDS_LFP_DATA);
> > -	if (!lvds_lfp_data)
> > -		return;
> > -
> > -	lvds_lfp_data_ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> > -	if (!lvds_lfp_data_ptrs)
> > -		return;
> > -
> >  	panel_dvo_timing = get_lvds_dvo_timing(lvds_lfp_data,
> >  					       lvds_lfp_data_ptrs,
> >  					       panel_type);
> > @@ -537,6 +528,24 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915)
> >  	}
> >  }
> >  
> > +static void
> > +parse_lfp_data(struct drm_i915_private *i915)
> > +{
> > +	const struct bdb_lvds_lfp_data *data;
> > +	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> > +
> > +	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> > +	if (!ptrs)
> > +		return;
> > +
> > +	data = find_section(i915, BDB_LVDS_LFP_DATA);
> > +	if (!data)
> > +		return;
> > +
> > +	if (!i915->vbt.lfp_lvds_vbt_mode)
> > +		parse_lfp_panel_dtd(i915, data, ptrs);
> 
> Could do an early return on i915->vbt.lfp_lvds_vbt_mode.

I'm adding more stuff that we don't want to skip to the end of
the function in later patches.

> 
> > +}
> > +
> >  static void
> >  parse_generic_dtd(struct drm_i915_private *i915)
> >  {
> > @@ -615,23 +624,6 @@ parse_generic_dtd(struct drm_i915_private *i915)
> >  	i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode;
> >  }
> >  
> > -static void
> > -parse_panel_dtd(struct drm_i915_private *i915)
> > -{
> > -	/*
> > -	 * Older VBTs provided provided DTD information for internal displays
> > -	 * through the "LFP panel DTD" block (42).  As of VBT revision 229,
> > -	 * that block is now deprecated and DTD information should be provided
> > -	 * via a newer "generic DTD" block (58).  Just to be safe, we'll
> > -	 * try the new generic DTD block first on VBT >= 229, but still fall
> > -	 * back to trying the old LFP block if that fails.
> > -	 */
> > -	if (i915->vbt.version >= 229)
> > -		parse_generic_dtd(i915);
> > -	if (!i915->vbt.lfp_lvds_vbt_mode)
> > -		parse_lfp_panel_dtd(i915);
> > -}
> > -
> >  static void
> >  parse_lfp_backlight(struct drm_i915_private *i915)
> >  {
> > @@ -2708,7 +2700,17 @@ void intel_bios_init(struct drm_i915_private *i915)
> >  	parse_general_features(i915);
> >  	parse_general_definitions(i915);
> >  	parse_panel_options(i915);
> > -	parse_panel_dtd(i915);
> > +	/*
> > +	 * Older VBTs provided DTD information for internal displays through
> > +	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
> > +	 * DTD information should be provided via a newer "generic DTD"
> > +	 * block (58).  Just to be safe, we'll try the new generic DTD block
> > +	 * first on VBT >= 229, but still fall back to trying the old LFP
> > +	 * block if that fails.
> > +	 */
> > +	if (i915->vbt.version >= 229)
> 
> I'd probably stick the vbt version check and the comment in
> parse_generic_dtd() instead of polluting the top level.

I suppose. Although that does make the ordering requirement between
parse_generic_dtd() vs. parse_lfp_data() a bit less clear. But maybe
this will all be rather temporary and we'll start transitioning
to a more on-demand based parsing of each thing.

> 
> Up to you if you want to do anything about the nitpicks,
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> 
> > +		parse_generic_dtd(i915);
> > +	parse_lfp_data(i915);
> >  	parse_lfp_backlight(i915);
> >  	parse_sdvo_panel_data(i915);
> >  	parse_driver_features(i915);
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 09/22] drm/i915/bios: Get access to the tail end of the LFP data block
  2022-04-07 17:07     ` Jani Nikula
@ 2022-04-08 14:04       ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-08 14:04 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 08:07:24PM +0300, Jani Nikula wrote:
> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > We need to start parsing stuff from the tail end of the LFP data block.
> > This is made awkward by the fact that the fp_timing table has variable
> > size. So we must use a bit more finesse to get the tail end, and to
> > make sure we allocate enough memory for it to make sure our struct
> > representation fits.
> >
> > v2: Rebase due to the preallocation of BDB blocks
> > v3: Rebase due to min_size WARN relocation
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c     | 39 ++++++++++++++++++-
> >  drivers/gpu/drm/i915/display/intel_vbt_defs.h | 17 ++++++++
> >  2 files changed, 55 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index d32091dad1b0..9a14d55b636c 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -188,7 +188,7 @@ static const struct {
> >  	{ .section_id = BDB_LVDS_LFP_DATA_PTRS,
> >  	  .min_size = sizeof(struct bdb_lvds_lfp_data_ptrs), },
> >  	{ .section_id = BDB_LVDS_LFP_DATA,
> > -	  .min_size = sizeof(struct bdb_lvds_lfp_data), },
> > +	  .min_size = 0, /* special case */ },
> >  	{ .section_id = BDB_LVDS_BACKLIGHT,
> >  	  .min_size = sizeof(struct bdb_lfp_backlight_data), },
> >  	{ .section_id = BDB_LFP_POWER,
> > @@ -203,6 +203,23 @@ static const struct {
> >  	  .min_size = sizeof(struct bdb_generic_dtd), },
> >  };
> >  
> > +static size_t lfp_data_min_size(struct drm_i915_private *i915)
> > +{
> > +	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> > +	size_t size;
> > +
> > +	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> 
> This depends on that block having been initialized before. Maybe the
> ordering requirement deserves a comment in bdb_blocks[].

Sure.

> 
> > +	if (!ptrs)
> > +		return 0;
> > +
> > +	size = sizeof(struct bdb_lvds_lfp_data);
> 
> Basically that and the struct definition are bogus, though? They assume
> a rigid structure. It might be true for some specific platforms, but
> generally likely not.
> 
> Or we could of course just add a comment about that in intel_vbt_defs.h.

I think I had that at some point. But I guess I lost it during
one of the many rewrites I did to this stuff.

> 
> > +	if (ptrs->panel_name.table_size)
> > +		size = max(size, ptrs->panel_name.offset +
> > +			   sizeof(struct bdb_lvds_lfp_data_tail));
> > +
> > +	return size;
> > +}
> > +
> >  static bool validate_lfp_data_ptrs(const void *bdb,
> >  				   const struct bdb_lvds_lfp_data_ptrs *ptrs)
> >  {
> > @@ -492,6 +509,9 @@ static void init_bdb_blocks(struct drm_i915_private *i915,
> >  		enum bdb_block_id section_id = bdb_blocks[i].section_id;
> >  		size_t min_size = bdb_blocks[i].min_size;
> >  
> > +		if (section_id == BDB_LVDS_LFP_DATA)
> > +			min_size = lfp_data_min_size(i915);
> 
> Nitpick, could also leave the "default" min size in bdb_blocks[], have
> lfp_data_min_size() return the other value or 0, and have the max()
> here. *shrug*

Could work. I was also pondering making .min_size a vfunc, but that
would lead to excessive boilerplate for all the other blocks. If only
we had lambdas...

> 
> > +
> >  		init_bdb_block(i915, bdb, section_id, min_size);
> >  	}
> >  }
> > @@ -562,6 +582,16 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
> >  	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
> >  }
> >  
> > +static const struct bdb_lvds_lfp_data_tail *
> > +get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
> > +		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
> > +{
> > +	if (ptrs->panel_name.table_size)
> > +		return (const void *)data + ptrs->panel_name.offset;
> > +	else
> > +		return NULL;
> > +}
> > +
> >  /* Parse general panel options */
> >  static void
> >  parse_panel_options(struct drm_i915_private *i915)
> > @@ -666,6 +696,7 @@ static void
> >  parse_lfp_data(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_lvds_lfp_data *data;
> > +	const struct bdb_lvds_lfp_data_tail *tail;
> >  	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> >  
> >  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> > @@ -678,6 +709,12 @@ parse_lfp_data(struct drm_i915_private *i915)
> >  
> >  	if (!i915->vbt.lfp_lvds_vbt_mode)
> >  		parse_lfp_panel_dtd(i915, data, ptrs);
> > +
> > +	tail = get_lfp_data_tail(data, ptrs);
> > +	if (!tail)
> > +		return;
> > +
> > +	(void)tail;
> 
> Mmmkay.
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> >  }
> >  
> >  static void
> > diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> > index e4a11c3e3f3e..64551d206aeb 100644
> > --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> > +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h
> > @@ -783,6 +783,23 @@ struct lvds_lfp_panel_name {
> >  	u8 name[13];
> >  } __packed;
> >  
> > +struct lvds_lfp_black_border {
> > +	u8 top; /*  227 */
> > +	u8 bottom; /*  227 */
> > +	u8 left; /* 238 */
> > +	u8 right; /* 238 */
> > +} __packed;
> > +
> > +struct bdb_lvds_lfp_data_tail {
> > +	struct lvds_lfp_panel_name panel_name[16]; /* 156-163? */
> > +	u16 scaling_enable; /* 187 */
> > +	u8 seamless_drrs_min_refresh_rate[16]; /* 188 */
> > +	u8 pixel_overlap_count[16]; /* 208 */
> > +	struct lvds_lfp_black_border black_border[16]; /* 227 */
> > +	u16 dual_lfp_port_sync_enable; /* 231 */
> > +	u16 gpu_dithering_for_banding_artifacts; /* 245 */
> > +} __packed;
> > +
> >  /*
> >   * Block 43 - LFP Backlight Control Data Block
> >   */
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts
  2022-04-07 17:23   ` Jani Nikula
@ 2022-04-08 14:09     ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-08 14:09 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 08:23:03PM +0300, Jani Nikula wrote:
> On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Parsing the panel specific data from VBT is currently happening
> > too early. Split the whole thing into global vs. panel specific
> > parts so that we can start doing the panel specific parsing at
> > a later time.
> 
> Might want to mention panel_type here somewhere, that's basically the
> split, right?

Yep. I'll try to clarify the commit msg a bit.

> 
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c    | 50 +++++++++++++-------
> >  drivers/gpu/drm/i915/display/intel_bios.h    |  1 +
> >  drivers/gpu/drm/i915/display/intel_display.c |  1 +
> >  3 files changed, 35 insertions(+), 17 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 1a7f1aa79827..da2b1932e10d 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -723,6 +723,9 @@ parse_generic_dtd(struct drm_i915_private *i915)
> >  	struct drm_display_mode *panel_fixed_mode;
> >  	int num_dtd;
> >  
> > +	if (i915->vbt.lfp_lvds_vbt_mode)
> > +		return;
> > +
> >  	generic_dtd = find_section(i915, BDB_GENERIC_DTD);
> >  	if (!generic_dtd)
> >  		return;
> > @@ -891,6 +894,9 @@ parse_sdvo_panel_data(struct drm_i915_private *i915)
> >  	struct drm_display_mode *panel_fixed_mode;
> >  	int index;
> >  
> > +	if (i915->vbt.sdvo_lvds_vbt_mode)
> > +		return;
> > +
> >  	index = i915->params.vbt_sdvo_panel_type;
> >  	if (index == -2) {
> >  		drm_dbg_kms(&i915->drm,
> > @@ -1419,6 +1425,9 @@ parse_mipi_config(struct drm_i915_private *i915)
> >  	int panel_type = i915->vbt.panel_type;
> >  	enum port port;
> >  
> > +	if (i915->vbt.dsi.config)
> > +		return;
> > +
> >  	/* parse MIPI blocks only if LFP type is MIPI */
> >  	if (!intel_bios_is_dsi_present(i915, &port))
> >  		return;
> > @@ -1739,6 +1748,9 @@ parse_mipi_sequence(struct drm_i915_private *i915)
> >  	u8 *data;
> >  	int index = 0;
> >  
> > +	if (i915->vbt.dsi.data)
> > +		return;
> > +
> 
> All of the above checks to (presumably) allow calling
> intel_bios_init_panel() multiple times feel a bit out of place here. At
> the very least need a mention in the commit message.

I can split that out for clarity. I didn't have these originally but
given the current reliance on the i915->vbt singleton I got a bit
scared what would happen on some weird machines with multiple panels.
IIRC some kind of native LVDS + SDVO LVDS machines may have existed
at some point.

Plenty of refactoring left here to split the parsed data to proper
per-panel things...

> 
> Regardless,
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> 
> >  	/* Only our generic panel driver uses the sequence block. */
> >  	if (i915->vbt.dsi.panel_id != MIPI_DSI_GENERIC_PANEL_ID)
> >  		return;
> > @@ -2878,6 +2890,27 @@ void intel_bios_init(struct drm_i915_private *i915)
> >  	/* Grab useful general definitions */
> >  	parse_general_features(i915);
> >  	parse_general_definitions(i915);
> > +	parse_driver_features(i915);
> > +
> > +	/* Depends on child device list */
> > +	parse_compression_parameters(i915);
> > +
> > +out:
> > +	if (!vbt) {
> > +		drm_info(&i915->drm,
> > +			 "Failed to find VBIOS tables (VBT)\n");
> > +		init_vbt_missing_defaults(i915);
> > +	}
> > +
> > +	/* Further processing on pre-parsed or generated child device data */
> > +	parse_sdvo_device_mapping(i915);
> > +	parse_ddi_ports(i915);
> > +
> > +	kfree(oprom_vbt);
> > +}
> > +
> > +void intel_bios_init_panel(struct drm_i915_private *i915)
> > +{
> >  	parse_panel_options(i915);
> >  	/*
> >  	 * Older VBTs provided DTD information for internal displays through
> > @@ -2892,29 +2925,12 @@ void intel_bios_init(struct drm_i915_private *i915)
> >  	parse_lfp_data(i915);
> >  	parse_lfp_backlight(i915);
> >  	parse_sdvo_panel_data(i915);
> > -	parse_driver_features(i915);
> >  	parse_panel_driver_features(i915);
> >  	parse_power_conservation_features(i915);
> >  	parse_edp(i915);
> >  	parse_psr(i915);
> >  	parse_mipi_config(i915);
> >  	parse_mipi_sequence(i915);
> > -
> > -	/* Depends on child device list */
> > -	parse_compression_parameters(i915);
> > -
> > -out:
> > -	if (!vbt) {
> > -		drm_info(&i915->drm,
> > -			 "Failed to find VBIOS tables (VBT)\n");
> > -		init_vbt_missing_defaults(i915);
> > -	}
> > -
> > -	/* Further processing on pre-parsed or generated child device data */
> > -	parse_sdvo_device_mapping(i915);
> > -	parse_ddi_ports(i915);
> > -
> > -	kfree(oprom_vbt);
> >  }
> >  
> >  /**
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> > index 4709c4d29805..c744d75fa435 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.h
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> > @@ -230,6 +230,7 @@ struct mipi_pps_data {
> >  } __packed;
> >  
> >  void intel_bios_init(struct drm_i915_private *dev_priv);
> > +void intel_bios_init_panel(struct drm_i915_private *dev_priv);
> >  void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
> >  bool intel_bios_is_valid_vbt(const void *buf, size_t size);
> >  bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
> > diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> > index eee185ed41c3..4ece4e7d0296 100644
> > --- a/drivers/gpu/drm/i915/display/intel_display.c
> > +++ b/drivers/gpu/drm/i915/display/intel_display.c
> > @@ -9650,6 +9650,7 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915)
> >  	}
> >  
> >  	intel_bios_init(i915);
> > +	intel_bios_init_panel(i915);
> >  
> >  	ret = intel_vga_register(i915);
> >  	if (ret)
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code
  2022-04-07 17:49   ` Jani Nikula
@ 2022-04-08 14:13     ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-08 14:13 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 08:49:00PM +0300, Jani Nikula wrote:
> On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Make the panel type code a bit more abstract along the
> > lines of the source of the panel type. For the moment
> > we have three classes: OpRegion, VBT, fallback.
> > Well introduce another one shortly.
> >
> > We can now also print out all the different panel types,
> > and indicate which one we ultimately selected. Could help
> > with debugging.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c | 47 ++++++++++++++++-------
> >  1 file changed, 34 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 26839263abf0..feef5aa97398 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -606,25 +606,46 @@ static int vbt_panel_type(struct drm_i915_private *i915)
> >  	return lvds_options->panel_type;
> >  }
> >  
> > +enum panel_type {
> > +	PANEL_TYPE_OPREGION,
> > +	PANEL_TYPE_VBT,
> > +	PANEL_TYPE_FALLBACK,
> > +};
> > +
> >  static int get_panel_type(struct drm_i915_private *i915)
> >  {
> > -	int ret;
> > +	struct {
> > +		const char *name;
> > +		int panel_type;
> > +	} panel_types[] = {
> > +		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
> > +		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
> > +		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
> > +	};
> > +	int i;
> >  
> > -	ret = intel_opregion_get_panel_type(i915);
> > -	if (ret >= 0) {
> > -		drm_WARN_ON(&i915->drm, ret > 0xf);
> > -		drm_dbg_kms(&i915->drm, "Panel type: %d (OpRegion)\n", ret);
> > -		return ret;
> > -	}
> > +	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
> > +	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);
> 
> I'd probably add a function pointer in the array, to be able to call
> these nicely in the loop. Needs a static wrapper function for
> intel_opregion_get_panel_type() in the follow-up to eat the edid
> parameter, but I think it's worth it.

Sure.

> 
> > +
> > +	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
> > +		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);
> 
> I know that's loud, but it's kind of annoying that the out of bounds
> value still goes through here.
> 
> >  
> > -	ret = vbt_panel_type(i915);
> > -	if (ret >= 0) {
> > -		drm_WARN_ON(&i915->drm, ret > 0xf);
> > -		drm_dbg_kms(&i915->drm, "Panel type: %d (VBT)\n", ret);
> > -		return ret;
> > +		if (panel_types[i].panel_type >= 0)
> > +			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
> > +				    panel_types[i].name, panel_types[i].panel_type);
> >  	}
> >  
> > -	return 0; /* fallback */
> > +	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
> > +		i = PANEL_TYPE_OPREGION;
> > +	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
> > +		i = PANEL_TYPE_VBT;
> > +	else
> > +		i = PANEL_TYPE_FALLBACK;
> 
> At this stage, we could set this in the loop too, but dunno how
> complicated that gets with the pnpid match rules.

I don't think the PNPID stuff really lends itself well to a loop
since it needs to consider both the VBT and PNPID pane types at
the same time.

> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> > +
> > +	drm_dbg_kms(&i915->drm, "Selected panel type (%s): %d\n",
> > +		    panel_types[i].name, panel_types[i].panel_type);
> > +
> > +	return panel_types[i].panel_type;
> >  }
> >  
> >  /* Parse general panel options */
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v4 18/22] drm/i915/bios: Determine panel type via PNPID match
  2022-04-07 17:55     ` Jani Nikula
@ 2022-04-08 14:51       ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-08 14:51 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 08:55:29PM +0300, Jani Nikula wrote:
> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Apparently when the VBT panel_type==0xff we should trawl through
> > the PNPID table and check for a match against the EDID. If a
> > match is found the index gives us the panel_type.
> >
> > Tried to match the Windows behaviour here with first looking
> > for an exact match, and if one isn't found we fall back to
> > looking for a match w/o the mfg year/week.
> 
> Does Windows also probe the EDID first, or does it use some side channel
> to use the GOP probed EDID? ISTR there's something in the EFI interface
> for this, but never looked deeper.

Lost some hair while trawling through it, but it does look it tries
the OpRegion mailbox first, then falls back to standard i2c stuff.

In a totally different codepath there's also an implementation of
APCI _DDC, but that doesn't seem get called from the eDP init path
that I was looking at so dunno what that is for.

> 
> >
> > v2: Rebase due to vlv_dsi changes
> >
> > Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5545
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> > ---
> >  drivers/gpu/drm/i915/display/icl_dsi.c    |  2 +-
> >  drivers/gpu/drm/i915/display/intel_bios.c | 82 ++++++++++++++++++++---
> >  drivers/gpu/drm/i915/display/intel_bios.h |  4 +-
> >  drivers/gpu/drm/i915/display/intel_dp.c   |  2 +-
> >  drivers/gpu/drm/i915/display/intel_lvds.c |  2 +-
> >  drivers/gpu/drm/i915/display/intel_sdvo.c |  2 +-
> >  drivers/gpu/drm/i915/display/vlv_dsi.c    |  2 +-
> >  7 files changed, 82 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
> > index 688176d4a54a..49715485a3a6 100644
> > --- a/drivers/gpu/drm/i915/display/icl_dsi.c
> > +++ b/drivers/gpu/drm/i915/display/icl_dsi.c
> > @@ -2048,7 +2048,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
> >  	/* attach connector to encoder */
> >  	intel_connector_attach_encoder(intel_connector, encoder);
> >  
> > -	intel_bios_init_panel(dev_priv);
> > +	intel_bios_init_panel(dev_priv, NULL);
> >  
> >  	mutex_lock(&dev->mode_config.mutex);
> >  	intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 0e76c554581a..4c0680356134 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -582,6 +582,14 @@ get_lvds_fp_timing(const struct bdb_lvds_lfp_data *data,
> >  	return (const void *)data + ptrs->ptr[index].fp_timing.offset;
> >  }
> >  
> > +static const struct lvds_pnp_id *
> > +get_lvds_pnp_id(const struct bdb_lvds_lfp_data *data,
> > +		const struct bdb_lvds_lfp_data_ptrs *ptrs,
> > +		int index)
> > +{
> > +	return (const void *)data + ptrs->ptr[index].panel_pnp_id.offset;
> > +}
> > +
> >  static const struct bdb_lvds_lfp_data_tail *
> >  get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
> >  		  const struct bdb_lvds_lfp_data_ptrs *ptrs)
> > @@ -592,6 +600,52 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
> >  		return NULL;
> >  }
> >  
> > +static int pnp_id_panel_type(struct drm_i915_private *i915,
> > +			     const struct edid *edid)
> > +{
> > +	const struct bdb_lvds_lfp_data *data;
> > +	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> > +	const struct lvds_pnp_id *edid_id;
> > +	struct lvds_pnp_id edid_id_nodate;
> > +	int i, best = -1;
> > +
> > +	if (!edid)
> > +		return -1;
> > +
> > +	edid_id = (const void *)&edid->mfg_id[0];
> > +
> > +	edid_id_nodate = *edid_id;
> > +	edid_id_nodate.mfg_week = 0;
> > +	edid_id_nodate.mfg_year = 0;
> > +
> > +	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> > +	if (!ptrs)
> > +		return -1;
> > +
> > +	data = find_section(i915, BDB_LVDS_LFP_DATA);
> > +	if (!data)
> > +		return -1;
> > +
> > +	for (i = 0; i < 16; i++) {
> > +		const struct lvds_pnp_id *vbt_id =
> > +			get_lvds_pnp_id(data, ptrs, i);
> > +
> > +		/* full match? */
> > +		if (!memcmp(vbt_id, edid_id, sizeof(*vbt_id)))
> > +			return i;
> > +
> > +		/*
> > +		 * Accept a match w/o date if no full match is found,
> > +		 * and the VBT entry does not specify a date.
> > +		 */
> > +		if (best < 0 &&
> > +		    !memcmp(vbt_id, &edid_id_nodate, sizeof(*vbt_id)))
> > +			best = i;
> > +	}
> > +
> > +	return best;
> > +}
> > +
> >  static int vbt_panel_type(struct drm_i915_private *i915)
> >  {
> >  	const struct bdb_lvds_options *lvds_options;
> > @@ -600,7 +654,8 @@ static int vbt_panel_type(struct drm_i915_private *i915)
> >  	if (!lvds_options)
> >  		return -1;
> >  
> > -	if (lvds_options->panel_type > 0xf) {
> > +	if (lvds_options->panel_type > 0xf &&
> > +	    lvds_options->panel_type != 0xff) {
> >  		drm_dbg_kms(&i915->drm, "Invalid VBT panel type 0x%x\n",
> >  			    lvds_options->panel_type);
> >  		return -1;
> > @@ -612,10 +667,12 @@ static int vbt_panel_type(struct drm_i915_private *i915)
> >  enum panel_type {
> >  	PANEL_TYPE_OPREGION,
> >  	PANEL_TYPE_VBT,
> > +	PANEL_TYPE_PNPID,
> >  	PANEL_TYPE_FALLBACK,
> >  };
> >  
> > -static int get_panel_type(struct drm_i915_private *i915)
> > +static int get_panel_type(struct drm_i915_private *i915,
> > +			  const struct edid *edid)
> >  {
> >  	struct {
> >  		const char *name;
> > @@ -623,15 +680,18 @@ static int get_panel_type(struct drm_i915_private *i915)
> >  	} panel_types[] = {
> >  		[PANEL_TYPE_OPREGION] = { .name = "OpRegion", .panel_type = -1, },
> >  		[PANEL_TYPE_VBT] = { .name = "VBT", .panel_type = -1, },
> > +		[PANEL_TYPE_PNPID] = { .name = "PNPID", .panel_type = -1, },
> >  		[PANEL_TYPE_FALLBACK] = { .name = "fallback", .panel_type = 0, },
> >  	};
> >  	int i;
> >  
> >  	panel_types[PANEL_TYPE_OPREGION].panel_type = intel_opregion_get_panel_type(i915);
> >  	panel_types[PANEL_TYPE_VBT].panel_type = vbt_panel_type(i915);
> > +	panel_types[PANEL_TYPE_PNPID].panel_type = pnp_id_panel_type(i915, edid);
> >  
> >  	for (i = 0; i < ARRAY_SIZE(panel_types); i++) {
> > -		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf);
> > +		drm_WARN_ON(&i915->drm, panel_types[i].panel_type > 0xf &&
> > +			    panel_types[i].panel_type != 0xff);
> >  
> >  		if (panel_types[i].panel_type >= 0)
> >  			drm_dbg_kms(&i915->drm, "Panel type (%s): %d\n",
> > @@ -640,7 +700,11 @@ static int get_panel_type(struct drm_i915_private *i915)
> >  
> >  	if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
> >  		i = PANEL_TYPE_OPREGION;
> > -	else if (panel_types[PANEL_TYPE_VBT].panel_type >= 0)
> > +	else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
> > +		 panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
> > +		i = PANEL_TYPE_PNPID;
> > +	else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
> > +		 panel_types[PANEL_TYPE_VBT].panel_type >= 0)
> >  		i = PANEL_TYPE_VBT;
> >  	else
> >  		i = PANEL_TYPE_FALLBACK;
> > @@ -653,7 +717,8 @@ static int get_panel_type(struct drm_i915_private *i915)
> >  
> >  /* Parse general panel options */
> >  static void
> > -parse_panel_options(struct drm_i915_private *i915)
> > +parse_panel_options(struct drm_i915_private *i915,
> > +		    const struct edid *edid)
> >  {
> >  	const struct bdb_lvds_options *lvds_options;
> >  	int panel_type;
> > @@ -665,7 +730,7 @@ parse_panel_options(struct drm_i915_private *i915)
> >  
> >  	i915->vbt.lvds_dither = lvds_options->pixel_dither;
> >  
> > -	panel_type = get_panel_type(i915);
> > +	panel_type = get_panel_type(i915, edid);
> >  
> >  	i915->vbt.panel_type = panel_type;
> >  
> > @@ -2953,9 +3018,10 @@ void intel_bios_init(struct drm_i915_private *i915)
> >  	kfree(oprom_vbt);
> >  }
> >  
> > -void intel_bios_init_panel(struct drm_i915_private *i915)
> > +void intel_bios_init_panel(struct drm_i915_private *i915,
> > +			   const struct edid *edid)
> >  {
> > -	parse_panel_options(i915);
> > +	parse_panel_options(i915, edid);
> >  	/*
> >  	 * Older VBTs provided DTD information for internal displays through
> >  	 * the "LFP panel tables" block (42).  As of VBT revision 229 the
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.h b/drivers/gpu/drm/i915/display/intel_bios.h
> > index c744d75fa435..be6d57bd0f5a 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.h
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.h
> > @@ -33,6 +33,7 @@
> >  #include <linux/types.h>
> >  
> >  struct drm_i915_private;
> > +struct edid;
> >  struct intel_bios_encoder_data;
> >  struct intel_crtc_state;
> >  struct intel_encoder;
> > @@ -230,7 +231,8 @@ struct mipi_pps_data {
> >  } __packed;
> >  
> >  void intel_bios_init(struct drm_i915_private *dev_priv);
> > -void intel_bios_init_panel(struct drm_i915_private *dev_priv);
> > +void intel_bios_init_panel(struct drm_i915_private *dev_priv,
> > +			   const struct edid *edid);
> >  void intel_bios_driver_remove(struct drm_i915_private *dev_priv);
> >  bool intel_bios_is_valid_vbt(const void *buf, size_t size);
> >  bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
> > diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> > index a1b5d7f5388b..41ac55a700e9 100644
> > --- a/drivers/gpu/drm/i915/display/intel_dp.c
> > +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> > @@ -5179,7 +5179,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
> >  	}
> >  	intel_connector->edid = edid;
> >  
> > -	intel_bios_init_panel(dev_priv);
> > +	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
> >  
> >  	intel_panel_add_edid_fixed_modes(intel_connector,
> >  					 dev_priv->vbt.drrs_type != DRRS_TYPE_NONE);
> > diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
> > index 554badf041f2..660bb95f2bf7 100644
> > --- a/drivers/gpu/drm/i915/display/intel_lvds.c
> > +++ b/drivers/gpu/drm/i915/display/intel_lvds.c
> > @@ -967,7 +967,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
> >  	}
> >  	intel_connector->edid = edid;
> >  
> > -	intel_bios_init_panel(dev_priv);
> > +	intel_bios_init_panel(dev_priv, IS_ERR(edid) ? NULL : edid);
> >  
> >  	/* Try EDID first */
> >  	intel_panel_add_edid_fixed_modes(intel_connector,
> > diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > index 661a1057a073..25195bc1edca 100644
> > --- a/drivers/gpu/drm/i915/display/intel_sdvo.c
> > +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
> > @@ -2900,7 +2900,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
> >  	if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
> >  		goto err;
> >  
> > -	intel_bios_init_panel(i915);
> > +	intel_bios_init_panel(i915, NULL);
> >  
> >  	/*
> >  	 * Fetch modes from VBT. For SDVO prefer the VBT mode since some
> > diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
> > index 08fb554ff7ad..1af6e927af9b 100644
> > --- a/drivers/gpu/drm/i915/display/vlv_dsi.c
> > +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
> > @@ -1929,7 +1929,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
> >  	else
> >  		intel_dsi->ports = BIT(port);
> >  
> > -	intel_bios_init_panel(dev_priv);
> > +	intel_bios_init_panel(dev_priv, NULL);
> >  
> >  	intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports;
> >  	intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports;
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v2 22/22] drm/i915/bios: Dump PNPID and panel name
  2022-04-07 18:07   ` Jani Nikula
@ 2022-04-08 14:52     ` Ville Syrjälä
  0 siblings, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-08 14:52 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 09:07:19PM +0300, Jani Nikula wrote:
> On Tue, 05 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Dump the panel PNPID and name from the VBT.
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c | 24 +++++++++++++++++++++++
> >  1 file changed, 24 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index d561551d6324..953526a7dc5d 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -25,6 +25,7 @@
> >   *
> >   */
> >  
> > +#include <drm/drm_edid.h>
> >  #include <drm/dp/drm_dp_helper.h>
> >  
> >  #include "display/intel_display.h"
> > @@ -597,6 +598,19 @@ get_lfp_data_tail(const struct bdb_lvds_lfp_data *data,
> >  		return NULL;
> >  }
> >  
> > +static void dump_pnp_id(struct drm_i915_private *i915,
> > +			const struct lvds_pnp_id *pnp_id,
> > +			const char *name)
> > +{
> > +	u16 mfg_name = be16_to_cpu((__force __be16)pnp_id->mfg_name);
> 
> Might just add the __be16 in the struct member?

Do we want that there since we copy the header to igt as well?

> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> > +	char vend[4];
> > +
> > +	drm_dbg_kms(&i915->drm, "%s PNPID mfg: %s (0x%x), prod: %u, serial: %u, week: %d, year: %d\n",
> > +		    name, drm_edid_decode_mfg_id(mfg_name, vend),
> > +		    pnp_id->mfg_name, pnp_id->product_code, pnp_id->serial,
> > +		    pnp_id->mfg_week, pnp_id->mfg_year + 1990);
> > +}
> > +
> >  static int pnp_id_panel_type(struct drm_i915_private *i915,
> >  			     const struct edid *edid)
> >  {
> > @@ -615,6 +629,8 @@ static int pnp_id_panel_type(struct drm_i915_private *i915,
> >  	edid_id_nodate.mfg_week = 0;
> >  	edid_id_nodate.mfg_year = 0;
> >  
> > +	dump_pnp_id(i915, edid_id, "EDID");
> > +
> >  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> >  	if (!ptrs)
> >  		return -1;
> > @@ -802,6 +818,7 @@ parse_lfp_data(struct drm_i915_private *i915)
> >  	const struct bdb_lvds_lfp_data *data;
> >  	const struct bdb_lvds_lfp_data_tail *tail;
> >  	const struct bdb_lvds_lfp_data_ptrs *ptrs;
> > +	const struct lvds_pnp_id *pnp_id;
> >  	int panel_type = i915->vbt.panel_type;
> >  
> >  	ptrs = find_section(i915, BDB_LVDS_LFP_DATA_PTRS);
> > @@ -815,10 +832,17 @@ parse_lfp_data(struct drm_i915_private *i915)
> >  	if (!i915->vbt.lfp_lvds_vbt_mode)
> >  		parse_lfp_panel_dtd(i915, data, ptrs);
> >  
> > +	pnp_id = get_lvds_pnp_id(data, ptrs, panel_type);
> > +	dump_pnp_id(i915, pnp_id, "Panel");
> > +
> >  	tail = get_lfp_data_tail(data, ptrs);
> >  	if (!tail)
> >  		return;
> >  
> > +	drm_dbg_kms(&i915->drm, "Panel name: %.*s\n",
> > +		    (int)sizeof(tail->panel_name[0].name),
> > +		    tail->panel_name[panel_type].name);
> > +
> >  	if (i915->vbt.version >= 188) {
> >  		i915->vbt.seamless_drrs_min_refresh_rate =
> >  			tail->seamless_drrs_min_refresh_rate[panel_type];
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [Intel-gfx] [PATCH v3 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them
  2022-04-07 16:53     ` Jani Nikula
  2022-04-07 18:18       ` Jani Nikula
@ 2022-04-12  8:19       ` Ville Syrjälä
  1 sibling, 0 replies; 72+ messages in thread
From: Ville Syrjälä @ 2022-04-12  8:19 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On Thu, Apr 07, 2022 at 07:53:13PM +0300, Jani Nikula wrote:
> On Wed, 06 Apr 2022, Ville Syrjala <ville.syrjala@linux.intel.com> wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >
> > Modern VBTs no longer contain the LFP data table pointers
> > block (41). We are expecting to have one in order to be able
> > to parse the LFP data block (42), so let's make one up.
> >
> > Since the fp_timing table has variable size we must somehow
> > determine its size. Rather than just hardcode it we look for
> > the terminator bytes (0xffff) to figure out where each table
> > entry starts. dvo_timing, panel_pnp_id, and panel_name are
> > expected to have fixed size.
> >
> > This has been observed on various machines, eg. TGL with BDB
> > version 240, CML with BDB version 231, etc. The most recent
> > VBT I've observed that still had block 41 had BDB version
> > 228. So presumably the cutoff (if an exact cutoff even exists)
> > is somewhere around BDB version 229-231.
> >
> > v2: kfree the thing we allocated, not the thing+3 bytes
> > v3: Do the debugprint only if we found the LFP data block
> >
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/display/intel_bios.c | 136 +++++++++++++++++++++-
> >  1 file changed, 135 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
> > index 8b118c54314d..d32091dad1b0 100644
> > --- a/drivers/gpu/drm/i915/display/intel_bios.c
> > +++ b/drivers/gpu/drm/i915/display/intel_bios.c
> > @@ -310,16 +310,146 @@ static bool fixup_lfp_data_ptrs(const void *bdb, void *ptrs_block)
> >  	return validate_lfp_data_ptrs(bdb, ptrs);
> >  }
> >  
> > +static const void *find_fp_timing_terminator(const u8 *data, int size)
> > +{
> > +	int i;
> > +
> > +	if (!data)
> > +		return NULL;
> > +
> > +	for (i = 0; i < size - 1; i++) {
> > +		if (data[i] == 0xff && data[i+1] == 0xff)
> > +			return &data[i];
> > +	}
> > +
> > +	return NULL;
> > +}
> > +
> > +static int make_lfp_data_ptr(struct lvds_lfp_data_ptr_table *table,
> > +			     int table_size, int total_size)
> > +{
> > +	if (total_size < table_size)
> > +		return total_size;
> > +
> > +	table->table_size = table_size;
> > +	table->offset = total_size - table_size;
> > +
> > +	return total_size - table_size;
> > +}
> > +
> > +static void next_lfp_data_ptr(struct lvds_lfp_data_ptr_table *next,
> > +			      const struct lvds_lfp_data_ptr_table *prev,
> > +			      int size)
> > +{
> > +	next->table_size = prev->table_size;
> > +	next->offset = prev->offset + size;
> > +}
> > +
> > +static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
> > +				    const void *bdb)
> > +{
> > +	int i, size, table_size, block_size, offset;
> > +	const void *t0, *t1, *block;
> > +	struct bdb_lvds_lfp_data_ptrs *ptrs;
> > +	void *ptrs_block;
> > +
> > +	block = find_raw_section(bdb, BDB_LVDS_LFP_DATA);
> > +	if (!block)
> > +		return NULL;
> > +
> > +	drm_dbg_kms(&i915->drm, "Generating LFP data table pointers\n");
> > +
> > +	block_size = get_blocksize(block);
> > +
> > +	size = block_size;
> > +	t0 = find_fp_timing_terminator(block, size);
> > +
> > +	size -= t0 - block - 2;
> > +	t1 = find_fp_timing_terminator(t0 + 2, size);
> 
> Need to NULL check t0 before using it.

I had the null check in find_fp_timing_terminator() but the +2
here does mean that it doesn't actually work. I'll move the check here.

-- 
Ville Syrjälä
Intel

^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2022-04-12  8:19 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-05 17:33 [Intel-gfx] [PATCH v2 00/22] drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Ville Syrjala
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 01/22] drm/i915/bios: Use the cached BDB version Ville Syrjala
2022-04-07 10:10   ` Jani Nikula
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 02/22] drm/i915/bios: Make copies of VBT data blocks Ville Syrjala
2022-04-06 13:38   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
2022-04-07 10:23     ` Jani Nikula
2022-04-07 11:18       ` Ville Syrjälä
2022-04-07 12:06         ` Jani Nikula
2022-04-07 12:23           ` Ville Syrjälä
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 03/22] drm/i915/bios: Use the copy of the LFP data table always Ville Syrjala
2022-04-07 10:36   ` Jani Nikula
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 04/22] drm/i915/bios: Validate LFP data table pointers Ville Syrjala
2022-04-07 16:07   ` Jani Nikula
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 05/22] drm/i915/bios: Trust the LFP data pointers Ville Syrjala
2022-04-07 16:12   ` Jani Nikula
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 06/22] drm/i915/bios: Validate the panel_name table Ville Syrjala
2022-04-07 16:14   ` Jani Nikula
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 07/22] drm/i915/bios: Reorder panel DTD parsing Ville Syrjala
2022-04-07 16:21   ` Jani Nikula
2022-04-08 13:59     ` Ville Syrjälä
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 08/22] drm/i915/bios: Generate LFP data table pointers if the VBT lacks them Ville Syrjala
2022-04-06 13:39   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
2022-04-07 12:24     ` Jani Nikula
2022-04-07 12:29       ` Ville Syrjälä
2022-04-07 16:53     ` Jani Nikula
2022-04-07 18:18       ` Jani Nikula
2022-04-12  8:19       ` Ville Syrjälä
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 09/22] drm/i915/bios: Get access to the tail end of the LFP data block Ville Syrjala
2022-04-06 13:40   ` [Intel-gfx] [PATCH v3 " Ville Syrjala
2022-04-07 17:07     ` Jani Nikula
2022-04-08 14:04       ` Ville Syrjälä
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 10/22] drm/i915/bios: Assume panel_type==0 if the VBT has bogus data Ville Syrjala
2022-04-07 17:11   ` Jani Nikula
2022-04-05 17:33 ` [Intel-gfx] [PATCH v2 11/22] drm/i915/bios: Split parse_driver_features() into two parts Ville Syrjala
2022-04-07 17:13   ` Jani Nikula
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 12/22] drm/i915/bios: Split VBT parsing to global vs. panel specific parts Ville Syrjala
2022-04-07 17:23   ` Jani Nikula
2022-04-08 14:09     ` Ville Syrjälä
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 13/22] drm/i915/pps: Split PPS init+sanitize in two Ville Syrjala
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 14/22] drm/i915/pps: Reinit PPS delays after VBT has been fully parsed Ville Syrjala
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 15/22] drm/i915/bios: Do panel specific VBT parsing later Ville Syrjala
2022-04-06 19:05   ` [Intel-gfx] [PATCH v4 " Ville Syrjala
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 16/22] drm/i915/bios: Extract get_panel_type() Ville Syrjala
2022-04-07 17:26   ` Jani Nikula
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 17/22] drm/i915/bios: Refactor panel_type code Ville Syrjala
2022-04-07 17:49   ` Jani Nikula
2022-04-08 14:13     ` Ville Syrjälä
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 18/22] drm/i915/bios: Determine panel type via PNPID match Ville Syrjala
2022-04-06 19:09   ` [Intel-gfx] [PATCH v4 " Ville Syrjala
2022-04-07 17:55     ` Jani Nikula
2022-04-08 14:51       ` Ville Syrjälä
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 19/22] drm/i915/bios: Parse the seamless DRRS min refresh rate Ville Syrjala
2022-04-07 17:56   ` Jani Nikula
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 20/22] drm/i915: Respect VBT " Ville Syrjala
2022-04-07 18:01   ` Jani Nikula
2022-04-05 17:34 ` [PATCH v2 21/22] drm/edid: Extract drm_edid_decode_mfg_id() Ville Syrjala
2022-04-05 17:34   ` [Intel-gfx] " Ville Syrjala
2022-04-07 18:02   ` Jani Nikula
2022-04-05 17:34 ` [Intel-gfx] [PATCH v2 22/22] drm/i915/bios: Dump PNPID and panel name Ville Syrjala
2022-04-07 18:07   ` Jani Nikula
2022-04-08 14:52     ` Ville Syrjälä
2022-04-05 22:55 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching Patchwork
2022-04-05 22:57 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-04-05 23:02 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
2022-04-05 23:27 ` [Intel-gfx] ✗ Fi.CI.BAT: failure " Patchwork
2022-04-06 18:17 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev4) Patchwork
2022-04-06 18:19 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-04-06 18:50 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-04-07  0:11 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/bios: Rework BDB block handling and PNPID->panel_type matching (rev6) Patchwork
2022-04-07  0:14 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2022-04-07  0:44 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-04-07  8:37 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.