diff options
| -rw-r--r-- | drivers/gpu/drm/drm_connector.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 52 | ||||
| -rw-r--r-- | include/drm/drm_edid.h | 2 |
3 files changed, 53 insertions, 14 deletions
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 482014137953..c4dfcbc861a1 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c | |||
| @@ -1231,6 +1231,19 @@ int drm_mode_connector_update_edid_property(struct drm_connector *connector, | |||
| 1231 | if (edid) | 1231 | if (edid) |
| 1232 | size = EDID_LENGTH * (1 + edid->extensions); | 1232 | size = EDID_LENGTH * (1 + edid->extensions); |
| 1233 | 1233 | ||
| 1234 | /* Set the display info, using edid if available, otherwise | ||
| 1235 | * reseting the values to defaults. This duplicates the work | ||
| 1236 | * done in drm_add_edid_modes, but that function is not | ||
| 1237 | * consistently called before this one in all drivers and the | ||
| 1238 | * computation is cheap enough that it seems better to | ||
| 1239 | * duplicate it rather than attempt to ensure some arbitrary | ||
| 1240 | * ordering of calls. | ||
| 1241 | */ | ||
| 1242 | if (edid) | ||
| 1243 | drm_add_display_info(connector, edid); | ||
| 1244 | else | ||
| 1245 | drm_reset_display_info(connector); | ||
| 1246 | |||
| 1234 | drm_object_property_set_value(&connector->base, | 1247 | drm_object_property_set_value(&connector->base, |
| 1235 | dev->mode_config.non_desktop_property, | 1248 | dev->mode_config.non_desktop_property, |
| 1236 | connector->display_info.non_desktop); | 1249 | connector->display_info.non_desktop); |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5dfe14763871..cb487148359a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -1731,7 +1731,7 @@ EXPORT_SYMBOL(drm_edid_duplicate); | |||
| 1731 | * | 1731 | * |
| 1732 | * Returns true if @vendor is in @edid, false otherwise | 1732 | * Returns true if @vendor is in @edid, false otherwise |
| 1733 | */ | 1733 | */ |
| 1734 | static bool edid_vendor(struct edid *edid, const char *vendor) | 1734 | static bool edid_vendor(const struct edid *edid, const char *vendor) |
| 1735 | { | 1735 | { |
| 1736 | char edid_vendor[3]; | 1736 | char edid_vendor[3]; |
| 1737 | 1737 | ||
| @@ -1749,7 +1749,7 @@ static bool edid_vendor(struct edid *edid, const char *vendor) | |||
| 1749 | * | 1749 | * |
| 1750 | * This tells subsequent routines what fixes they need to apply. | 1750 | * This tells subsequent routines what fixes they need to apply. |
| 1751 | */ | 1751 | */ |
| 1752 | static u32 edid_get_quirks(struct edid *edid) | 1752 | static u32 edid_get_quirks(const struct edid *edid) |
| 1753 | { | 1753 | { |
| 1754 | const struct edid_quirk *quirk; | 1754 | const struct edid_quirk *quirk; |
| 1755 | int i; | 1755 | int i; |
| @@ -2813,7 +2813,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, | |||
| 2813 | /* | 2813 | /* |
| 2814 | * Search EDID for CEA extension block. | 2814 | * Search EDID for CEA extension block. |
| 2815 | */ | 2815 | */ |
| 2816 | static u8 *drm_find_edid_extension(struct edid *edid, int ext_id) | 2816 | static u8 *drm_find_edid_extension(const struct edid *edid, int ext_id) |
| 2817 | { | 2817 | { |
| 2818 | u8 *edid_ext = NULL; | 2818 | u8 *edid_ext = NULL; |
| 2819 | int i; | 2819 | int i; |
| @@ -2835,12 +2835,12 @@ static u8 *drm_find_edid_extension(struct edid *edid, int ext_id) | |||
| 2835 | return edid_ext; | 2835 | return edid_ext; |
| 2836 | } | 2836 | } |
| 2837 | 2837 | ||
| 2838 | static u8 *drm_find_cea_extension(struct edid *edid) | 2838 | static u8 *drm_find_cea_extension(const struct edid *edid) |
| 2839 | { | 2839 | { |
| 2840 | return drm_find_edid_extension(edid, CEA_EXT); | 2840 | return drm_find_edid_extension(edid, CEA_EXT); |
| 2841 | } | 2841 | } |
| 2842 | 2842 | ||
| 2843 | static u8 *drm_find_displayid_extension(struct edid *edid) | 2843 | static u8 *drm_find_displayid_extension(const struct edid *edid) |
| 2844 | { | 2844 | { |
| 2845 | return drm_find_edid_extension(edid, DISPLAYID_EXT); | 2845 | return drm_find_edid_extension(edid, DISPLAYID_EXT); |
| 2846 | } | 2846 | } |
| @@ -4363,7 +4363,7 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db) | |||
| 4363 | } | 4363 | } |
| 4364 | 4364 | ||
| 4365 | static void drm_parse_cea_ext(struct drm_connector *connector, | 4365 | static void drm_parse_cea_ext(struct drm_connector *connector, |
| 4366 | struct edid *edid) | 4366 | const struct edid *edid) |
| 4367 | { | 4367 | { |
| 4368 | struct drm_display_info *info = &connector->display_info; | 4368 | struct drm_display_info *info = &connector->display_info; |
| 4369 | const u8 *edid_ext; | 4369 | const u8 *edid_ext; |
| @@ -4397,11 +4397,33 @@ static void drm_parse_cea_ext(struct drm_connector *connector, | |||
| 4397 | } | 4397 | } |
| 4398 | } | 4398 | } |
| 4399 | 4399 | ||
| 4400 | static void drm_add_display_info(struct drm_connector *connector, | 4400 | /* A connector has no EDID information, so we've got no EDID to compute quirks from. Reset |
| 4401 | struct edid *edid, u32 quirks) | 4401 | * all of the values which would have been set from EDID |
| 4402 | */ | ||
| 4403 | void | ||
| 4404 | drm_reset_display_info(struct drm_connector *connector) | ||
| 4402 | { | 4405 | { |
| 4403 | struct drm_display_info *info = &connector->display_info; | 4406 | struct drm_display_info *info = &connector->display_info; |
| 4404 | 4407 | ||
| 4408 | info->width_mm = 0; | ||
| 4409 | info->height_mm = 0; | ||
| 4410 | |||
| 4411 | info->bpc = 0; | ||
| 4412 | info->color_formats = 0; | ||
| 4413 | info->cea_rev = 0; | ||
| 4414 | info->max_tmds_clock = 0; | ||
| 4415 | info->dvi_dual = false; | ||
| 4416 | |||
| 4417 | info->non_desktop = 0; | ||
| 4418 | } | ||
| 4419 | EXPORT_SYMBOL_GPL(drm_reset_display_info); | ||
| 4420 | |||
| 4421 | u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid) | ||
| 4422 | { | ||
| 4423 | struct drm_display_info *info = &connector->display_info; | ||
| 4424 | |||
| 4425 | u32 quirks = edid_get_quirks(edid); | ||
| 4426 | |||
| 4405 | info->width_mm = edid->width_cm * 10; | 4427 | info->width_mm = edid->width_cm * 10; |
| 4406 | info->height_mm = edid->height_cm * 10; | 4428 | info->height_mm = edid->height_cm * 10; |
| 4407 | 4429 | ||
| @@ -4414,11 +4436,13 @@ static void drm_add_display_info(struct drm_connector *connector, | |||
| 4414 | 4436 | ||
| 4415 | info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP); | 4437 | info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP); |
| 4416 | 4438 | ||
| 4439 | DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop); | ||
| 4440 | |||
| 4417 | if (edid->revision < 3) | 4441 | if (edid->revision < 3) |
| 4418 | return; | 4442 | return quirks; |
| 4419 | 4443 | ||
| 4420 | if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) | 4444 | if (!(edid->input & DRM_EDID_INPUT_DIGITAL)) |
| 4421 | return; | 4445 | return quirks; |
| 4422 | 4446 | ||
| 4423 | drm_parse_cea_ext(connector, edid); | 4447 | drm_parse_cea_ext(connector, edid); |
| 4424 | 4448 | ||
| @@ -4438,7 +4462,7 @@ static void drm_add_display_info(struct drm_connector *connector, | |||
| 4438 | 4462 | ||
| 4439 | /* Only defined for 1.4 with digital displays */ | 4463 | /* Only defined for 1.4 with digital displays */ |
| 4440 | if (edid->revision < 4) | 4464 | if (edid->revision < 4) |
| 4441 | return; | 4465 | return quirks; |
| 4442 | 4466 | ||
| 4443 | switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { | 4467 | switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) { |
| 4444 | case DRM_EDID_DIGITAL_DEPTH_6: | 4468 | case DRM_EDID_DIGITAL_DEPTH_6: |
| @@ -4473,7 +4497,9 @@ static void drm_add_display_info(struct drm_connector *connector, | |||
| 4473 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; | 4497 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
| 4474 | if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) | 4498 | if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422) |
| 4475 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; | 4499 | info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
| 4500 | return quirks; | ||
| 4476 | } | 4501 | } |
| 4502 | EXPORT_SYMBOL_GPL(drm_add_display_info); | ||
| 4477 | 4503 | ||
| 4478 | static int validate_displayid(u8 *displayid, int length, int idx) | 4504 | static int validate_displayid(u8 *displayid, int length, int idx) |
| 4479 | { | 4505 | { |
| @@ -4627,14 +4653,12 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) | |||
| 4627 | return 0; | 4653 | return 0; |
| 4628 | } | 4654 | } |
| 4629 | 4655 | ||
| 4630 | quirks = edid_get_quirks(edid); | ||
| 4631 | |||
| 4632 | /* | 4656 | /* |
| 4633 | * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. | 4657 | * CEA-861-F adds ycbcr capability map block, for HDMI 2.0 sinks. |
| 4634 | * To avoid multiple parsing of same block, lets parse that map | 4658 | * To avoid multiple parsing of same block, lets parse that map |
| 4635 | * from sink info, before parsing CEA modes. | 4659 | * from sink info, before parsing CEA modes. |
| 4636 | */ | 4660 | */ |
| 4637 | drm_add_display_info(connector, edid, quirks); | 4661 | quirks = drm_add_display_info(connector, edid); |
| 4638 | 4662 | ||
| 4639 | /* | 4663 | /* |
| 4640 | * EDID spec says modes should be preferred in this order: | 4664 | * EDID spec says modes should be preferred in this order: |
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 2ec41d032e56..efe6d5a8e834 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h | |||
| @@ -465,6 +465,8 @@ struct edid *drm_get_edid(struct drm_connector *connector, | |||
| 465 | struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, | 465 | struct edid *drm_get_edid_switcheroo(struct drm_connector *connector, |
| 466 | struct i2c_adapter *adapter); | 466 | struct i2c_adapter *adapter); |
| 467 | struct edid *drm_edid_duplicate(const struct edid *edid); | 467 | struct edid *drm_edid_duplicate(const struct edid *edid); |
| 468 | void drm_reset_display_info(struct drm_connector *connector); | ||
| 469 | u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edid); | ||
| 468 | int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); | 470 | int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); |
| 469 | 471 | ||
| 470 | u8 drm_match_cea_mode(const struct drm_display_mode *to_match); | 472 | u8 drm_match_cea_mode(const struct drm_display_mode *to_match); |
