mirror of
https://github.com/torvalds/linux.git
synced 2024-11-20 02:51:44 +00:00
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: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
c1b5dea097
commit
6363ee6f49
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user