drm/radeon: use a fetch function to get the edid
authorAlex Deucher <alexander.deucher@amd.com>
Tue, 15 Jul 2014 15:00:47 +0000 (11:00 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 5 Aug 2014 12:53:30 +0000 (08:53 -0400)
We keep a cached version of the edid in radeon_connector which
we use for determining connectedness and when to enable certain
features like hdmi audio, etc.  When the user uses the firmware
interface to override the driver with some other edid the driver's
copy is never updated.  The fetch function will check if there
is a user supplied edid and update the driver's copy if there
is.

bug:
https://bugs.freedesktop.org/show_bug.cgi?id=80691

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/dce6_afmt.c
drivers/gpu/drm/radeon/evergreen_hdmi.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_mode.h

index 34fe641c3b516afdc17d6be6dea20373cb0fe36c..a7f2ddf09a9d20024a0cca95e70d3f3b8ff5fc12 100644 (file)
@@ -716,7 +716,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                        if (radeon_connector->use_digital &&
                            (radeon_connector->audio == RADEON_AUDIO_ENABLE))
                                return ATOM_ENCODER_MODE_HDMI;
-                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                       else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                                 (radeon_connector->audio == RADEON_AUDIO_AUTO))
                                return ATOM_ENCODER_MODE_HDMI;
                        else if (radeon_connector->use_digital)
@@ -735,7 +735,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                if (radeon_audio != 0) {
                        if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
                                return ATOM_ENCODER_MODE_HDMI;
-                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                       else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                                 (radeon_connector->audio == RADEON_AUDIO_AUTO))
                                return ATOM_ENCODER_MODE_HDMI;
                        else
@@ -755,7 +755,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
                } else if (radeon_audio != 0) {
                        if (radeon_connector->audio == RADEON_AUDIO_ENABLE)
                                return ATOM_ENCODER_MODE_HDMI;
-                       else if (drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                       else if (drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                                 (radeon_connector->audio == RADEON_AUDIO_AUTO))
                                return ATOM_ENCODER_MODE_HDMI;
                        else
index edcf1598da6bbee4bd451ba054f092ce0669db54..ab29f953a767318c5e06de2115a9cfde017a9c82 100644 (file)
@@ -175,7 +175,7 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder)
                return;
        }
 
-       sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+       sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
        if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
@@ -238,7 +238,7 @@ void dce6_afmt_write_sad_regs(struct drm_encoder *encoder)
                return;
        }
 
-       sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+       sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
        if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
index 1ec0e6e83f9f3492151d097c839251029996d6f6..278c7a139d748f770467a53d4cf19a920c9bb2ef 100644 (file)
@@ -117,7 +117,7 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder)
                return;
        }
 
-       sad_count = drm_edid_to_speaker_allocation(radeon_connector->edid, &sadb);
+       sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector), &sadb);
        if (sad_count <= 0) {
                DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sad_count);
                return;
@@ -172,7 +172,7 @@ static void evergreen_hdmi_write_sad_regs(struct drm_encoder *encoder)
                return;
        }
 
-       sad_count = drm_edid_to_sad(radeon_connector->edid, &sads);
+       sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
        if (sad_count <= 0) {
                DRM_ERROR("Couldn't read SADs: %d\n", sad_count);
                return;
index 5b5d28ad9ba59ef4b7e6c98c557df7245b1c1d8e..1651defb2df72a7f1610f1a296f80f1a245cb1de 100644 (file)
@@ -107,7 +107,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
        case DRM_MODE_CONNECTOR_DVII:
        case DRM_MODE_CONNECTOR_HDMIB:
                if (radeon_connector->use_digital) {
-                       if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                                if (connector->display_info.bpc)
                                        bpc = connector->display_info.bpc;
                        }
@@ -115,7 +115,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
                break;
        case DRM_MODE_CONNECTOR_DVID:
        case DRM_MODE_CONNECTOR_HDMIA:
-               if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+               if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                        if (connector->display_info.bpc)
                                bpc = connector->display_info.bpc;
                }
@@ -124,7 +124,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
                dig_connector = radeon_connector->con_priv;
                if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) ||
                    (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) ||
-                   drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                   drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                        if (connector->display_info.bpc)
                                bpc = connector->display_info.bpc;
                }
@@ -148,7 +148,7 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
                break;
        }
 
-       if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
+       if (drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                /* hdmi deep color only implemented on DCE4+ */
                if ((bpc > 8) && !ASIC_IS_DCE4(rdev)) {
                        DRM_DEBUG("%s: HDMI deep color %d bpc unsupported. Using 8 bpc.\n",
@@ -262,6 +262,21 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector,
        return NULL;
 }
 
+struct edid *radeon_connector_edid(struct drm_connector *connector)
+{
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_property_blob *edid_blob = connector->edid_blob_ptr;
+
+       if (radeon_connector->edid) {
+               return radeon_connector->edid;
+       } else if (edid_blob) {
+               struct edid *edid = kmemdup(edid_blob->data, edid_blob->length, GFP_KERNEL);
+               if (edid)
+                       radeon_connector->edid = edid;
+       }
+       return radeon_connector->edid;
+}
+
 static void radeon_connector_get_edid(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
@@ -1366,7 +1381,7 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
                    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
                    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
                        return MODE_OK;
-               else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+               else if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                        /* HDMI 1.3+ supports max clock of 340 Mhz */
                        if (mode->clock > 340000)
                                return MODE_CLOCK_HIGH;
@@ -1660,7 +1675,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
                    (radeon_dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) {
                        return radeon_dp_mode_valid_helper(connector, mode);
                } else {
-                       if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                                /* HDMI 1.3+ supports max clock of 340 Mhz */
                                if (mode->clock > 340000)
                                        return MODE_CLOCK_HIGH;
index 004f30c170f6cb6d00f7e5c4671badefc70e26e0..a966074a4fbaea80d65effff6788abf99f4beb24 100644 (file)
@@ -1691,7 +1691,7 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
                            (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) &&
                            ((radeon_encoder->underscan_type == UNDERSCAN_ON) ||
                             ((radeon_encoder->underscan_type == UNDERSCAN_AUTO) &&
-                             drm_detect_hdmi_monitor(radeon_connector->edid) &&
+                             drm_detect_hdmi_monitor(radeon_connector_edid(connector)) &&
                              is_hdtv_mode(mode)))) {
                                if (radeon_encoder->underscan_hborder != 0)
                                        radeon_crtc->h_border = radeon_encoder->underscan_hborder;
index bd4959ca23aa1a451703ce89ab0bf9a812b87fab..3c2094c25b537516a8b181e26fd2bca00dca0411 100644 (file)
@@ -343,7 +343,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
        case DRM_MODE_CONNECTOR_HDMIB:
                if (radeon_connector->use_digital) {
                        /* HDMI 1.3 supports up to 340 Mhz over single link */
-                       if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                                if (pixel_clock > 340000)
                                        return true;
                                else
@@ -365,7 +365,7 @@ bool radeon_dig_monitor_is_duallink(struct drm_encoder *encoder,
                        return false;
                else {
                        /* HDMI 1.3 supports up to 340 Mhz over single link */
-                       if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector->edid)) {
+                       if (ASIC_IS_DCE6(rdev) && drm_detect_hdmi_monitor(radeon_connector_edid(connector))) {
                                if (pixel_clock > 340000)
                                        return true;
                                else
index 9c2bfcd3576e5ca6428ee01a7c1d60e777f73f0b..9ccae81c7d8856ef3976183ba8d84eec01b2b2f1 100644 (file)
@@ -689,6 +689,8 @@ extern bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector);
 extern bool radeon_connector_is_dp12_capable(struct drm_connector *connector);
 extern int radeon_get_monitor_bpc(struct drm_connector *connector);
 
+extern struct edid *radeon_connector_edid(struct drm_connector *connector);
+
 extern void radeon_connector_hotplug(struct drm_connector *connector);
 extern int radeon_dp_mode_valid_helper(struct drm_connector *connector,
                                       struct drm_display_mode *mode);