Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6363ee6f authored by Zhao Yakui's avatar Zhao Yakui Committed by Eric Anholt
Browse files

drm/i915: parse child device from VBT

On some laptops there is no HDMI/DP. But the xrandr still reports
several disconnected HDMI/display ports. In such case the user will be
confused.
 >DVI1 disconnected (normal left inverted right x axis y axis)
 >DP1 disconnected (normal left inverted right x axis y axis)
 >DVI2 disconnected (normal left inverted right x axis y axis)
 >DP2 disconnected (normal left inverted right x axis y axis)
 >DP3 disconnected (normal left inverted right x axis y axis)

This patch set is to use the child device parsed in VBT to decide whether
the HDMI/DP/LVDS/TV should be initialized.

Parse the child device from VBT.

The device class type is also added for LFP, TV, HDMI, DP output.

https://bugs.freedesktop.org/show_bug.cgi?id=22785



Signed-off-by: default avatarZhao Yakui <yakui.zhao@intel.com>
Reviewed-by: default avatarAdam Jackson <ajax@redhat.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent c1b5dea0
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1526,6 +1526,15 @@ int i915_driver_unload(struct drm_device *dev)
	}

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		/*
		 * free the memory space allocated for the child device
		 * config parsed from VBT
		 */
		if (dev_priv->child_dev && dev_priv->child_dev_num) {
			kfree(dev_priv->child_dev);
			dev_priv->child_dev = NULL;
			dev_priv->child_dev_num = 0;
		}
		drm_irq_uninstall(dev);
		vga_client_register(dev->pdev, NULL, NULL, NULL);
	}
+2 −0
Original line number Diff line number Diff line
@@ -545,6 +545,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 */
+65 −0
Original line number Diff line number Diff line
@@ -404,6 +404,70 @@ parse_driver_features(struct drm_i915_private *dev_priv,
		dev_priv->render_reclock_avail = true;
}

static void
parse_device_mapping(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;

	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
	if (!p_defs) {
		DRM_DEBUG_KMS("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_KMS("different child size is found. Invalid.\n");
		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);
	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_KMS("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_KMS("No memory space for child device\n");
		return;
	}

	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;
		count++;
		memcpy((void *)child_dev_ptr, (void *)p_child,
					sizeof(*p_child));
	}
	return;
}
/**
 * intel_init_bios - initialize VBIOS settings & find VBT
 * @dev: DRM device
@@ -455,6 +519,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(dev_priv, bdb);
	parse_driver_features(dev_priv, bdb);

	pci_unmap_rom(pdev, bios);
+17 −0
Original line number Diff line number Diff line
@@ -549,4 +549,21 @@ bool intel_init_bios(struct drm_device *dev);
#define   SWF14_APM_STANDBY	0x1
#define   SWF14_APM_RESTORE	0x0

/* Add the device class for LFP, TV, HDMI */
#define	 DEVICE_TYPE_INT_LFP	0x1022
#define	 DEVICE_TYPE_INT_TV	0x1009
#define	 DEVICE_TYPE_HDMI	0x60D2
#define	 DEVICE_TYPE_DP		0x68C6
#define	 DEVICE_TYPE_eDP	0x78C6

/* define the DVO port for HDMI output type */
#define		DVO_B		1
#define		DVO_C		2
#define		DVO_D		3

/* define the PORT for DP output type */
#define		PORT_IDPB	7
#define		PORT_IDPC	8
#define		PORT_IDPD	9

#endif /* _I830_BIOS_H_ */