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__ */ |