When running HDMI compliance tests we noticed that sometimes the edid changes but the get_modes() function is not called so the edid is not updated. Moving the edid reading to the detect() callback ensures that the edid is correctly updated after an hotplug. Signed-off-by: Jose Abreu <joabreu@xxxxxxxxxxxx> Cc: Carlos Palminha <palminha@xxxxxxxxxxxx> Cc: Archit Taneja <architt@xxxxxxxxxxxxxx> Cc: David Airlie <airlied@xxxxxxxx> Cc: Russell King <rmk+kernel@xxxxxxxxxxxxxxxx> Cc: Fabio Estevam <fabio.estevam@xxxxxxxxxxxxx> Cc: Daniel Vetter <daniel.vetter@xxxxxxxx> Cc: Takashi Iwai <tiwai@xxxxxxx> Cc: Vladimir Zapolskiy <vladimir_zapolskiy@xxxxxxxxxx> Cc: Thierry Reding <treding@xxxxxxxxxx> Cc: dri-devel@xxxxxxxxxxxxxxxxxxxxx Cc: linux-kernel@xxxxxxxxxxxxxxx --- This patch was only introduced in v3. drivers/gpu/drm/bridge/dw-hdmi.c | 67 +++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c index 9122a20..c795888 100644 --- a/drivers/gpu/drm/bridge/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/dw-hdmi.c @@ -31,8 +31,6 @@ #include "dw-hdmi.h" #include "dw-hdmi-audio.h" -#define HDMI_EDID_LEN 512 - #define RGB 0 #define YCBCR444 1 #define YCBCR422_16BITS 2 @@ -117,7 +115,7 @@ struct dw_hdmi { int vic; - u8 edid[HDMI_EDID_LEN]; + struct edid *edid; bool cable_plugin; bool phy_enabled; @@ -1457,6 +1455,7 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) { struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector); + bool connected; mutex_lock(&hdmi->mutex); hdmi->force = DRM_FORCE_UNSPECIFIED; @@ -1464,7 +1463,40 @@ dw_hdmi_connector_detect(struct drm_connector *connector, bool force) dw_hdmi_update_phy_mask(hdmi); mutex_unlock(&hdmi->mutex); - return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ? + connected = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD; + + if (connected && hdmi->ddc) { + if (hdmi->edid) { + drm_mode_connector_update_edid_property(connector, + NULL); + kfree(hdmi->edid); + hdmi->edid = NULL; + } + + hdmi->edid = drm_get_edid(connector, hdmi->ddc); + if (hdmi->edid) { + dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", + hdmi->edid->width_cm, + hdmi->edid->height_cm); + drm_mode_connector_update_edid_property(connector, + hdmi->edid); + drm_edid_to_eld(connector, hdmi->edid); + + hdmi->sink_is_hdmi = + drm_detect_hdmi_monitor(hdmi->edid); + hdmi->sink_has_audio = + drm_detect_monitor_audio(hdmi->edid); + hdmi->sink_supports_ai = + connector->eld[5] & (0x1 << 1); + } else { + dev_dbg(hdmi->dev, "failed to get edid\n"); + hdmi->sink_is_hdmi = false; + hdmi->sink_has_audio = false; + hdmi->sink_supports_ai = false; + } + } + + return connected ? connector_status_connected : connector_status_disconnected; } @@ -1472,33 +1504,10 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector) { struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi, connector); - struct edid *edid; int ret = 0; - if (!hdmi->ddc) - return 0; - - edid = drm_get_edid(connector, hdmi->ddc); - if (edid) { - dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n", - edid->width_cm, edid->height_cm); - - hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); - hdmi->sink_has_audio = drm_detect_monitor_audio(edid); - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - /* Store the ELD */ - drm_edid_to_eld(connector, edid); - kfree(edid); - - hdmi->sink_supports_ai = connector->eld[5] & (0x1 << 1); - } else { - dev_dbg(hdmi->dev, "failed to get edid\n"); - hdmi->sink_is_hdmi = false; - hdmi->sink_has_audio = false; - hdmi->sink_supports_ai = false; - } - + if (hdmi->edid) + ret = drm_add_edid_modes(connector, hdmi->edid); return ret; } -- 2.1.4 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel