diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_bios.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_bios.c | 51 | 
1 files changed, 48 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 300aee3296c..f806fcc54e0 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -59,6 +59,16 @@ find_section(struct bdb_header *bdb, int section_id)  	return NULL;  } +static u16 +get_blocksize(void *p) +{ +	u16 *block_ptr, block_size; + +	block_ptr = (u16 *)((char *)p - 2); +	block_size = *block_ptr; +	return block_size; +} +  static void  fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,  			struct lvds_dvo_timing *dvo_timing) @@ -215,6 +225,41 @@ parse_general_features(struct drm_i915_private *dev_priv,  }  static void +parse_general_definitions(struct drm_i915_private *dev_priv, +			  struct bdb_header *bdb) +{ +	struct bdb_general_definitions *general; +	const int crt_bus_map_table[] = { +		GPIOB, +		GPIOA, +		GPIOC, +		GPIOD, +		GPIOE, +		GPIOF, +	}; + +	/* Set sensible defaults in case we can't find the general block +	   or it is the wrong chipset */ +	dev_priv->crt_ddc_bus = -1; + +	general = find_section(bdb, BDB_GENERAL_DEFINITIONS); +	if (general) { +		u16 block_size = get_blocksize(general); +		if (block_size >= sizeof(*general)) { +			int bus_pin = general->crt_ddc_gmbus_pin; +			DRM_DEBUG("crt_ddc_bus_pin: %d\n", bus_pin); +			if ((bus_pin >= 1) && (bus_pin <= 6)) { +				dev_priv->crt_ddc_bus = +					crt_bus_map_table[bus_pin-1]; +			} +		} else { +			DRM_DEBUG("BDB_GD too small (%d). Invalid.\n", +				  block_size); +		} +	} +} + +static void  parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,  		       struct bdb_header *bdb)  { @@ -222,7 +267,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,  	struct bdb_general_definitions *p_defs;  	struct child_device_config *p_child;  	int i, child_device_num, count; -	u16	block_size, *block_ptr; +	u16	block_size;  	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);  	if (!p_defs) { @@ -240,8 +285,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,  		return;  	}  	/* get the block size of general definitions */ -	block_ptr = (u16 *)((char *)p_defs - 2); -	block_size = *block_ptr; +	block_size = get_blocksize(p_defs);  	/* get the number of child device */  	child_device_num = (block_size - sizeof(*p_defs)) /  				sizeof(*p_child); @@ -362,6 +406,7 @@ intel_init_bios(struct drm_device *dev)  	/* Grab useful general definitions */  	parse_general_features(dev_priv, bdb); +	parse_general_definitions(dev_priv, bdb);  	parse_lfp_panel_data(dev_priv, bdb);  	parse_sdvo_panel_data(dev_priv, bdb);  	parse_sdvo_device_mapping(dev_priv, bdb);  |