aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMa Ling <ling.ma@intel.com>2009-03-26 07:26:23 -0400
committerDave Airlie <airlied@redhat.com>2009-03-29 04:31:49 -0400
commitf23c20c83d523e5f8cda1f8f7ed52fe6afffbe29 (patch)
treec0888eeee7f76b46151264294222bf74190b385c
parentdba5ed0cd12d8db5c0d2e1c869c2a50c5bcf6743 (diff)
drm: detect hdmi monitor by hdmi identifier (v3)
Sometime we need to communicate with HDMI monitor by sending audio or video info frame, so we have to know monitor type. However if user utilize HDMI-DVI adapter to connect DVI monitor, hardware detection will incorrectly show the monitor is HDMI. HDMI spec tell us that any device containing IEEE registration Identifier will be treated as HDMI device. The patch intends to detect HDMI monitor by this rule. Signed-off-by: Ma Ling <ling.ma@intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-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__ */