Skip to content

Commit 90e4f15

Browse files
vsyrjaladanvet
authored andcommitted
drm/i915: Fix the VBT child device parsing for BSW
Recent BSW VBT has a VBT child device size 37 bytes instead of the 33 bytes our code assumes. This means we fail to parse the VBT and thus fail to detect eDP ports properly and just register them as DP ports instead. Fix it up by using the reported child device size from the VBT instead of assuming it matches out struct defintions. The latest spec I have shows that the child device size should be 36 bytes for rev >= 195, however on my BSW the size is actually 37 bytes. And our current struct definition is 33 bytes. Feels like the entire VBT parses would need to be rewritten to handle changes in the layout better, but for now I've decided to do just the bare minimum to get my eDP port back. Cc: Vijay Purushothaman <vijay.a.purushothaman@linux.intel.com> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
1 parent a4e0bed commit 90e4f15

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

drivers/gpu/drm/i915/intel_bios.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,12 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
447447
}
448448
}
449449

450+
static union child_device_config *
451+
child_device_ptr(struct bdb_general_definitions *p_defs, int i)
452+
{
453+
return (void *) &p_defs->devices[i * p_defs->child_dev_size];
454+
}
455+
450456
static void
451457
parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
452458
struct bdb_header *bdb)
@@ -476,10 +482,10 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
476482
block_size = get_blocksize(p_defs);
477483
/* get the number of child device */
478484
child_device_num = (block_size - sizeof(*p_defs)) /
479-
sizeof(*p_child);
485+
p_defs->child_dev_size;
480486
count = 0;
481487
for (i = 0; i < child_device_num; i++) {
482-
p_child = &(p_defs->devices[i]);
488+
p_child = child_device_ptr(p_defs, i);
483489
if (!p_child->old.device_type) {
484490
/* skip the device block if device type is invalid */
485491
continue;
@@ -1067,25 +1073,19 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
10671073
DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
10681074
return;
10691075
}
1070-
/* judge whether the size of child device meets the requirements.
1071-
* If the child device size obtained from general definition block
1072-
* is different with sizeof(struct child_device_config), skip the
1073-
* parsing of sdvo device info
1074-
*/
1075-
if (p_defs->child_dev_size != sizeof(*p_child)) {
1076-
/* different child dev size . Ignore it */
1077-
DRM_DEBUG_KMS("different child size is found. Invalid.\n");
1076+
if (p_defs->child_dev_size < sizeof(*p_child)) {
1077+
DRM_ERROR("General definiton block child device size is too small.\n");
10781078
return;
10791079
}
10801080
/* get the block size of general definitions */
10811081
block_size = get_blocksize(p_defs);
10821082
/* get the number of child device */
10831083
child_device_num = (block_size - sizeof(*p_defs)) /
1084-
sizeof(*p_child);
1084+
p_defs->child_dev_size;
10851085
count = 0;
10861086
/* get the number of child device that is present */
10871087
for (i = 0; i < child_device_num; i++) {
1088-
p_child = &(p_defs->devices[i]);
1088+
p_child = child_device_ptr(p_defs, i);
10891089
if (!p_child->common.device_type) {
10901090
/* skip the device block if device type is invalid */
10911091
continue;
@@ -1105,7 +1105,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
11051105
dev_priv->vbt.child_dev_num = count;
11061106
count = 0;
11071107
for (i = 0; i < child_device_num; i++) {
1108-
p_child = &(p_defs->devices[i]);
1108+
p_child = child_device_ptr(p_defs, i);
11091109
if (!p_child->common.device_type) {
11101110
/* skip the device block if device type is invalid */
11111111
continue;

drivers/gpu/drm/i915/intel_bios.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,9 @@ struct bdb_general_definitions {
277277
* And the device num is related with the size of general definition
278278
* block. It is obtained by using the following formula:
279279
* number = (block_size - sizeof(bdb_general_definitions))/
280-
* sizeof(child_device_config);
280+
* defs->child_dev_size;
281281
*/
282-
union child_device_config devices[0];
282+
uint8_t devices[0];
283283
} __packed;
284284

285285
/* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */

0 commit comments

Comments
 (0)