diff options
| -rw-r--r-- | drivers/gpu/drm/drm_edid.c | 62 | ||||
| -rw-r--r-- | include/drm/drm_crtc.h | 1 |
2 files changed, 63 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fab2bdf9c423..c67400067b85 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -742,6 +742,68 @@ end: | |||
| 742 | } | 742 | } |
| 743 | EXPORT_SYMBOL(drm_get_edid); | 743 | EXPORT_SYMBOL(drm_get_edid); |
| 744 | 744 | ||
| 745 | #define HDMI_IDENTIFIER 0x000C03 | ||
| 746 | #define VENDOR_BLOCK 0x03 | ||
| 747 | /** | ||
| 748 | * drm_detect_hdmi_monitor - detect whether monitor is hdmi. | ||
| 749 | * @edid: monitor EDID information | ||
| 750 | * | ||
| 751 | * Parse the CEA extension according to CEA-861-B. | ||
| 752 | * Return true if HDMI, false if not or unknown. | ||
| 753 | */ | ||
| 754 | bool drm_detect_hdmi_monitor(struct edid *edid) | ||
| 755 | { | ||
| 756 | char *edid_ext = NULL; | ||
| 757 | int i, hdmi_id, edid_ext_num; | ||
| 758 | int start_offset, end_offset; | ||
| 759 | bool is_hdmi = false; | ||
| 760 | |||
| 761 | /* No EDID or EDID extensions */ | ||
| 762 | if (edid == NULL || edid->extensions == 0) | ||
| 763 | goto end; | ||
| 764 | |||
| 765 | /* Chose real EDID extension number */ | ||
| 766 | edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ? | ||
| 767 | MAX_EDID_EXT_NUM : edid->extensions; | ||
| 768 | |||
| 769 | /* Find CEA extension */ | ||
| 770 | for (i = 0; i < edid_ext_num; i++) { | ||
| 771 | edid_ext = (char *)edid + EDID_LENGTH * (i + 1); | ||
| 772 | /* This block is CEA extension */ | ||
| 773 | if (edid_ext[0] == 0x02) | ||
| 774 | break; | ||
| 775 | } | ||
| 776 | |||
| 777 | if (i == edid_ext_num) | ||
| 778 | goto end; | ||
| 779 | |||
| 780 | /* Data block offset in CEA extension block */ | ||
| 781 | start_offset = 4; | ||
| 782 | end_offset = edid_ext[2]; | ||
| 783 | |||
| 784 | /* | ||
| 785 | * Because HDMI identifier is in Vendor Specific Block, | ||
| 786 | * search it from all data blocks of CEA extension. | ||
| 787 | */ | ||
| 788 | for (i = start_offset; i < end_offset; | ||
| 789 | /* Increased by data block len */ | ||
| 790 | i += ((edid_ext[i] & 0x1f) + 1)) { | ||
| 791 | /* Find vendor specific block */ | ||
| 792 | if ((edid_ext[i] >> 5) == VENDOR_BLOCK) { | ||
| 793 | hdmi_id = edid_ext[i + 1] | (edid_ext[i + 2] << 8) | | ||
| 794 | edid_ext[i + 3] << 16; | ||
| 795 | /* Find HDMI identifier */ | ||
| 796 | if (hdmi_id == HDMI_IDENTIFIER) | ||
| 797 | is_hdmi = true; | ||
| 798 | break; | ||
| 799 | } | ||
| 800 | } | ||
| 801 | |||
| 802 | end: | ||
| 803 | return is_hdmi; | ||
| 804 | } | ||
| 805 | EXPORT_SYMBOL(drm_detect_hdmi_monitor); | ||
| 806 | |||
| 745 | /** | 807 | /** |
| 746 | * drm_add_edid_modes - add modes from EDID data, if available | 808 | * drm_add_edid_modes - add modes from EDID data, if available |
| 747 | * @connector: connector we're probing | 809 | * @connector: connector we're probing |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 9022b2468182..3c1924c010e8 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
| @@ -732,4 +732,5 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev, | |||
| 732 | void *data, struct drm_file *file_priv); | 732 | void *data, struct drm_file *file_priv); |
| 733 | extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, | 733 | extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, |
| 734 | void *data, struct drm_file *file_priv); | 734 | void *data, struct drm_file *file_priv); |
| 735 | extern bool drm_detect_hdmi_monitor(struct edid *edid); | ||
| 735 | #endif /* __DRM_CRTC_H__ */ | 736 | #endif /* __DRM_CRTC_H__ */ |
