[Intel-gfx] [PATCH] drm/i915: Fix the VBT child device parsing for BSW
Damien Lespiau
damien.lespiau at intel.com
Wed Apr 8 10:09:37 PDT 2015
On Wed, Mar 25, 2015 at 06:45:58PM +0200, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at linux.intel.com>
>
> 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 at linux.intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
Two minor comments, but, in any case, this is:
Reviewed-by: Damien Lespiau <damien.lespiau at intel.com>
> ---
> drivers/gpu/drm/i915/intel_bios.c | 26 +++++++++++++-------------
> drivers/gpu/drm/i915/intel_bios.h | 4 ++--
> 2 files changed, 15 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index c684085..4cbd325 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -447,6 +447,12 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
> }
> }
>
> +static union child_device_config *
> +child_device_ptr(struct bdb_general_definitions *p_defs, int i)
> +{
> + return (void *) &p_defs->devices[i * p_defs->child_dev_size];
> +}
We could use a child_device_num() helper as well.
> static void
> parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
> struct bdb_header *bdb)
> @@ -476,10 +482,10 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
> block_size = get_blocksize(p_defs);
> /* get the number of child device */
> child_device_num = (block_size - sizeof(*p_defs)) /
> - sizeof(*p_child);
> + p_defs->child_dev_size;
> count = 0;
> for (i = 0; i < child_device_num; i++) {
> - p_child = &(p_defs->devices[i]);
> + p_child = child_device_ptr(p_defs, i);
> if (!p_child->old.device_type) {
> /* skip the device block if device type is invalid */
> continue;
> @@ -1067,25 +1073,19 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
> DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
> return;
> }
> - /* judge whether the size of child device meets the requirements.
> - * If the child device size obtained from general definition block
> - * is different with sizeof(struct child_device_config), skip the
> - * parsing of sdvo device info
> - */
> - if (p_defs->child_dev_size != sizeof(*p_child)) {
> - /* different child dev size . Ignore it */
> - DRM_DEBUG_KMS("different child size is found. Invalid.\n");
> + if (p_defs->child_dev_size < sizeof(*p_child)) {
> + DRM_ERROR("General definiton block child device size is too small.\n");
definition
> return;
> }
> /* get the block size of general definitions */
> block_size = get_blocksize(p_defs);
> /* get the number of child device */
> child_device_num = (block_size - sizeof(*p_defs)) /
> - sizeof(*p_child);
> + p_defs->child_dev_size;
> count = 0;
> /* get the number of child device that is present */
> for (i = 0; i < child_device_num; i++) {
> - p_child = &(p_defs->devices[i]);
> + p_child = child_device_ptr(p_defs, i);
> if (!p_child->common.device_type) {
> /* skip the device block if device type is invalid */
> continue;
> @@ -1105,7 +1105,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
> dev_priv->vbt.child_dev_num = count;
> count = 0;
> for (i = 0; i < child_device_num; i++) {
> - p_child = &(p_defs->devices[i]);
> + p_child = child_device_ptr(p_defs, i);
> if (!p_child->common.device_type) {
> /* skip the device block if device type is invalid */
> continue;
> diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
> index 6afd5be..af0b476 100644
> --- a/drivers/gpu/drm/i915/intel_bios.h
> +++ b/drivers/gpu/drm/i915/intel_bios.h
> @@ -277,9 +277,9 @@ struct bdb_general_definitions {
> * And the device num is related with the size of general definition
> * block. It is obtained by using the following formula:
> * number = (block_size - sizeof(bdb_general_definitions))/
> - * sizeof(child_device_config);
> + * defs->child_dev_size;
> */
> - union child_device_config devices[0];
> + uint8_t devices[0];
> } __packed;
>
> /* Mask for DRRS / Panel Channel / SSC / BLT control bits extraction */
> --
> 2.0.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
More information about the Intel-gfx
mailing list