diff options
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 67 |
1 files changed, 57 insertions, 10 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3d0a4da661bc..0454da505687 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2796,7 +2796,7 @@ u32 drm_edid_get_panel_id(struct i2c_adapter *adapter) * the EDID then we'll just return 0. */ - base_block = kmalloc(EDID_LENGTH, GFP_KERNEL); + base_block = kzalloc(EDID_LENGTH, GFP_KERNEL); if (!base_block) return 0; @@ -3424,10 +3424,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto connector->base.id, connector->name); return NULL; } - if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { - drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Composite sync not supported\n", - connector->base.id, connector->name); - } /* it is incorrect if hsync/vsync width is zero */ if (!hsync_pulse_width || !vsync_pulse_width) { @@ -3474,10 +3470,27 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connecto if (info->quirks & EDID_QUIRK_DETAILED_SYNC_PP) { mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC; } else { - mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? - DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; - mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? - DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; + switch (pt->misc & DRM_EDID_PT_SYNC_MASK) { + case DRM_EDID_PT_ANALOG_CSYNC: + case DRM_EDID_PT_BIPOLAR_ANALOG_CSYNC: + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Analog composite sync!\n", + connector->base.id, connector->name); + mode->flags |= DRM_MODE_FLAG_CSYNC | DRM_MODE_FLAG_NCSYNC; + break; + case DRM_EDID_PT_DIGITAL_CSYNC: + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Digital composite sync!\n", + connector->base.id, connector->name); + mode->flags |= DRM_MODE_FLAG_CSYNC; + mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? + DRM_MODE_FLAG_PCSYNC : DRM_MODE_FLAG_NCSYNC; + break; + case DRM_EDID_PT_DIGITAL_SEPARATE_SYNC: + mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? + DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; + mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? + DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; + break; + } } set_size: @@ -6433,6 +6446,29 @@ static void drm_reset_display_info(struct drm_connector *connector) info->quirks = 0; } +static void update_displayid_info(struct drm_connector *connector, + const struct drm_edid *drm_edid) +{ + struct drm_display_info *info = &connector->display_info; + const struct displayid_block *block; + struct displayid_iter iter; + + displayid_iter_edid_begin(drm_edid, &iter); + displayid_iter_for_each(block, &iter) { + if (displayid_version(&iter) == DISPLAY_ID_STRUCTURE_VER_20 && + (displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_VR || + displayid_primary_use(&iter) == PRIMARY_USE_HEAD_MOUNTED_AR)) + info->non_desktop = true; + + /* + * We're only interested in the base section here, no need to + * iterate further. + */ + break; + } + displayid_iter_end(&iter); +} + static void update_display_info(struct drm_connector *connector, const struct drm_edid *drm_edid) { @@ -6463,6 +6499,8 @@ static void update_display_info(struct drm_connector *connector, info->color_formats |= DRM_COLOR_FORMAT_RGB444; drm_parse_cea_ext(connector, drm_edid); + update_displayid_info(connector, drm_edid); + /* * Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3? * @@ -7242,6 +7280,15 @@ static void drm_parse_tiled_block(struct drm_connector *connector, } } +static bool displayid_is_tiled_block(const struct displayid_iter *iter, + const struct displayid_block *block) +{ + return (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_12 && + block->tag == DATA_BLOCK_TILED_DISPLAY) || + (displayid_version(iter) == DISPLAY_ID_STRUCTURE_VER_20 && + block->tag == DATA_BLOCK_2_TILED_DISPLAY_TOPOLOGY); +} + static void _drm_update_tile_info(struct drm_connector *connector, const struct drm_edid *drm_edid) { @@ -7252,7 +7299,7 @@ static void _drm_update_tile_info(struct drm_connector *connector, displayid_iter_edid_begin(drm_edid, &iter); displayid_iter_for_each(block, &iter) { - if (block->tag == DATA_BLOCK_TILED_DISPLAY) + if (displayid_is_tiled_block(&iter, block)) drm_parse_tiled_block(connector, block); } displayid_iter_end(&iter); |