diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index e5b138b..0725907 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1548,6 +1548,15 @@ int i915_driver_unload(struct drm_device *dev)
 		mutex_unlock(&dev->struct_mutex);
 		drm_mm_takedown(&dev_priv->vram);
 		i915_gem_lastclose(dev);
+		/*
+		 * free the memory space allocated for the child device
+		 * config parsed from VBT
+		 */
+		if (dev_priv->child_dev_num && dev_priv->child_dev) {
+			kfree(dev_priv->child_dev);
+			dev_priv->child_dev = NULL;
+			dev_priv->child_dev_num = 0;
+		}
 	}
 
 	pci_dev_put(dev_priv->bridge_dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 57204e2..58d1cbf 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -253,7 +253,7 @@ typedef struct drm_i915_private {
 	unsigned int lvds_vbt:1;
 	unsigned int int_crt_support:1;
 	unsigned int lvds_use_ssc:1;
-	unsigned int edp_support:1;
+	unsigned int lvds_config:2;
 	int lvds_ssc_freq;
 
 	struct notifier_block lid_notifier;
@@ -534,6 +534,8 @@ typedef struct drm_i915_private {
 	struct timer_list idle_timer;
 	bool busy;
 	u16 orig_clock;
+	int child_dev_num;
+	struct child_device_config *child_dev;
 } drm_i915_private_t;
 
 /** driver private structure attached to each drm_gem_object */
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 96cd256..47fe8bc 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -355,17 +355,77 @@ parse_driver_features(struct drm_i915_private *dev_priv,
 	if (!driver)
 		return;
 
-	if (driver && SUPPORTS_EDP(dev) &&
-	    driver->lvds_config == BDB_DRIVER_FEATURE_EDP) {
-		dev_priv->edp_support = 1;
-	} else {
-		dev_priv->edp_support = 0;
-	}
+	dev_priv->lvds_config = driver->lvds_config;
 
-	if (driver && driver->dual_frequency)
+	if (driver->dual_frequency)
 		dev_priv->render_reclock_avail = true;
 }
 
+static void
+parse_device_mapping_from_vbt(struct drm_i915_private *dev_priv,
+		       struct bdb_header *bdb)
+{
+	struct bdb_general_definitions *p_defs;
+	struct child_device_config *p_child, *child_dev_ptr;
+	int i, child_device_num, count;
+	u16	block_size, *block_ptr;
+
+	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	if (!p_defs) {
+		DRM_DEBUG("No general definition block is found\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("different child size is found. Invalid.\n");
+		return;
+	}
+	/* get the block size of general definitions */
+	block_ptr = (u16 *)((char *)p_defs - 2);
+	block_size = *block_ptr;
+	/* get the number of child device */
+	child_device_num = (block_size - sizeof(*p_defs)) /
+				sizeof(*p_child);
+	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]);
+		if (!p_child->device_type) {
+			/* skip the device block if device type is invalid */
+			continue;
+		}
+		count++;
+	}
+	if (!count) {
+		DRM_DEBUG("no child dev is parsed from VBT \n");
+		return;
+	}
+	dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL);
+	if (!dev_priv->child_dev) {
+		DRM_DEBUG("Can't allocate memory space for child device\n");
+	}
+	dev_priv->child_dev_num = count;
+	count = 0;
+	for (i = 0; i < child_device_num; i++) {
+		p_child = &(p_defs->devices[i]);
+		if (!p_child->device_type) {
+			/* skip the device block if device type is invalid */
+			continue;
+		}
+		child_dev_ptr = dev_priv->child_dev + count;
+		printk(KERN_DEBUG "initial %p, result %p, size %d\n",
+				dev_priv->child_dev, child_dev_ptr, sizeof(*p_child) * count);
+		count++;
+		memcpy((void *)child_dev_ptr, (void *)p_child, sizeof(*p_child));
+	}
+	return;
+}
+
 /**
  * intel_init_bios - initialize VBIOS settings & find VBT
  * @dev: DRM device
@@ -417,6 +477,7 @@ intel_init_bios(struct drm_device *dev)
 	parse_lfp_panel_data(dev_priv, bdb);
 	parse_sdvo_panel_data(dev_priv, bdb);
 	parse_sdvo_device_mapping(dev_priv, bdb);
+	parse_device_mapping_from_vbt(dev_priv, bdb);
 	parse_driver_features(dev_priv, bdb);
 
 	pci_unmap_rom(pdev, bios);
diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
index 0f8e5f6..efef36b 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -161,13 +161,16 @@ struct bdb_general_features {
 #define DEVICE_TYPE_EFP_DVI_I		0x6053
 #define DEVICE_TYPE_EFP_DVI_D_DUAL	0x6152
 #define DEVICE_TYPE_EFP_DVI_D_HDCP	0x60d2
+#define DEVICE_TYPE_EFP_HDMI		DEVICE_TYPE_EFP_DVI_D_HDCP
 #define DEVICE_TYPE_OPENLDI_HOTPLUG_PWR	0x6062
 #define DEVICE_TYPE_OPENLDI_DUALPIX	0x6162
 #define DEVICE_TYPE_LFP_PANELLINK	0x5012
 #define DEVICE_TYPE_LFP_CMOS_PWR	0x5042
+#define DEVICE_TYPE_LFP_LVDS		0x1022
 #define DEVICE_TYPE_LFP_LVDS_PWR	0x5062
 #define DEVICE_TYPE_LFP_LVDS_DUAL	0x5162
 #define DEVICE_TYPE_LFP_LVDS_DUAL_HDCP	0x51e2
+#define DEVICE_TYPE_DISPLAYPORT		0x68c6
 
 #define DEVICE_CFG_NONE		0x00
 #define DEVICE_CFG_12BIT_DVOB	0x01
@@ -192,6 +195,10 @@ struct bdb_general_features {
 #define DEVICE_PORT_DVOA	0x00 /* none on 845+ */
 #define DEVICE_PORT_DVOB	0x01
 #define DEVICE_PORT_DVOC	0x02
+#define DEVICE_PORT_DVOD	0x03
+#define DEVICE_PORT_IDPB	0x07
+#define DEVICE_PORT_IDPC	0x08
+#define DEVICE_PORT_IDPD	0x09
 
 struct child_device_config {
 	u16 handle;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index d834475..3b25374 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1228,6 +1228,45 @@ intel_dp_hot_plug(struct intel_output *intel_output)
 		intel_dp_check_link_status(intel_output);
 }
 
+/*
+ * Enumerate the child dev array parsed from VBT to check whether
+ * the given DP is present.
+ * If it is present, return 1.
+ * If it is not present, return false.
+ * If no child dev is parsed from VBT, it assumes that the given
+ * DP is present.
+ */
+int dp_is_present_in_vbt(struct drm_device *dev, int dp_reg)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct child_device_config *p_child;
+	int i, dp_port, ret;
+
+	if (!dev_priv->child_dev_num)
+		return 1;
+
+	if (dp_reg == DP_B)
+		dp_port = DEVICE_PORT_IDPB;
+	else if (dp_reg == DP_C)
+		dp_port = DEVICE_PORT_IDPC;
+	else
+		dp_port = DEVICE_PORT_IDPD;
+
+	ret = 0;
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		p_child = dev_priv->child_dev + i;
+		/*
+		 * If the device type is not HDMI, continue.
+		 */
+		if (p_child->device_type != DEVICE_TYPE_DISPLAYPORT)
+			continue;
+		/* Find the DP port */
+		if (p_child->dvo_port == dp_port)
+			ret = 1;
+	}
+	return ret;
+}
+
 void
 intel_dp_init(struct drm_device *dev, int output_reg)
 {
@@ -1237,6 +1276,11 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	struct intel_dp_priv *dp_priv;
 	const char *name = NULL;
 
+	if (!dp_is_present_in_vbt(dev, output_reg)) {
+		DRM_DEBUG("DP is not present, ignoring\n");
+		return;
+	}
+
 	intel_output = kcalloc(sizeof(struct intel_output) + 
 			       sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
 	if (!intel_output)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index 663ab6d..2450eba 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -207,6 +207,45 @@ static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
 	.destroy = intel_hdmi_enc_destroy,
 };
 
+/*
+ * Enumerate the child dev array parsed from VBT to check whether
+ * the given HDMI is present.
+ * If it is present, return 1.
+ * If it is not present, return false.
+ * If no child dev is parsed from VBT, it assumes that the given
+ * HDMI is present.
+ */
+int hdmi_is_present_in_vbt(struct drm_device *dev, int hdmi_reg)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct child_device_config *p_child;
+	int i, hdmi_port, ret;
+
+	if (!dev_priv->child_dev_num)
+		return 1;
+
+	if (hdmi_reg == SDVOB)
+		hdmi_port = DEVICE_PORT_DVOB;
+	else if (hdmi_reg == SDVOC)
+		hdmi_port = DEVICE_PORT_DVOC;
+	else if (hdmi_reg == HDMIB)
+		hdmi_port = DEVICE_PORT_DVOB;
+	else if (hdmi_reg == HDMIC)
+		hdmi_port = DEVICE_PORT_DVOC;
+	else if (hdmi_reg == HDMID)
+		hdmi_port = DEVICE_PORT_DVOD;
+
+	ret = 0;
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		p_child = dev_priv->child_dev + i;
+		if (p_child->device_type != DEVICE_TYPE_EFP_HDMI)
+			continue;
+		/* Find the HDMI port */
+		if (p_child->dvo_port == hdmi_port)
+			ret = 1;
+	}
+	return ret;
+}
 
 void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 {
@@ -215,6 +254,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
 	struct intel_output *intel_output;
 	struct intel_hdmi_priv *hdmi_priv;
 
+	if (!hdmi_is_present_in_vbt(dev, sdvox_reg)) {
+		DRM_DEBUG("HDMI is not present, ignoring\n");
+		return;
+	}
+
 	intel_output = kcalloc(sizeof(struct intel_output) +
 			       sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL);
 	if (!intel_output)
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 05598ae..fc9e73d 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -913,6 +913,38 @@ static int intel_lid_present(void)
 }
 #endif
 
+static int device_is_lvds(u32 device)
+{
+	return device == DEVICE_TYPE_LFP_LVDS ||
+	       device == DEVICE_TYPE_LFP_LVDS_PWR ||
+	       device == DEVICE_TYPE_LFP_LVDS_DUAL ||
+	       device == DEVICE_TYPE_LFP_LVDS_DUAL_HDCP;
+}
+
+static int intel_lvds_present_in_vbt(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct child_device_config *child;
+	int i;
+
+	if (!dev_priv->child_dev_num)
+		return 1;
+
+	if (dev_priv->lvds_config == BDB_DRIVER_FEATURE_NO_LVDS)
+		return 0;
+
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		child = dev_priv->child_dev + i;
+
+		if (!(device_is_lvds(child->device_type)))
+			continue;
+		if (child->addin_offset)
+			return 1;
+	}
+
+	return 0;
+}
+
 /**
  * intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -936,20 +968,17 @@ void intel_lvds_init(struct drm_device *dev)
 	if (dmi_check_system(intel_no_lvds))
 		return;
 
-	/* Assume that any device without an ACPI LID device also doesn't
-	 * have an integrated LVDS.  We would be better off parsing the BIOS
-	 * to get a reliable indicator, but that code isn't written yet.
-	 *
-	 * In the case of all-in-one desktops using LVDS that we've seen,
-	 * they're using SDVO LVDS.
+	/*
+	 * If a lid device is present, assume LVDS is present. Otherwise,
+	 * walk the child device config for a valid-looking LVDS entry.
 	 */
-	if (!intel_lid_present())
+	if (!intel_lid_present() && !intel_lvds_present_in_vbt(dev))
 		return;
 
 	if (IS_IGDNG(dev)) {
 		if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
 			return;
-		if (dev_priv->edp_support) {
+		if (dev_priv->lvds_config == BDB_DRIVER_FEATURE_EDP) {
 			DRM_DEBUG("disable LVDS for eDP support\n");
 			return;
 		}
