aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_edid.c62
-rw-r--r--include/drm/drm_crtc.h1
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}
743EXPORT_SYMBOL(drm_get_edid); 743EXPORT_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 */
754bool 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
802end:
803 return is_hdmi;
804}
805EXPORT_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);
733extern int drm_mode_gamma_set_ioctl(struct drm_device *dev, 733extern 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);
735extern bool drm_detect_hdmi_monitor(struct edid *edid);
735#endif /* __DRM_CRTC_H__ */ 736#endif /* __DRM_CRTC_H__ */