Messages in this thread Patch in this message | | | From | Jose Abreu <> | Subject | [PATCH 3/3 v3] drm: bridge/dw-hdmi: Move edid reading to .detect() callback | Date | Thu, 4 Aug 2016 11:44:51 +0100 |
| |
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@synopsys.com> Cc: Carlos Palminha <palminha@synopsys.com> Cc: Archit Taneja <architt@codeaurora.org> Cc: David Airlie <airlied@linux.ie> Cc: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Fabio Estevam <fabio.estevam@freescale.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Takashi Iwai <tiwai@suse.de> Cc: Vladimir Zapolskiy <vladimir_zapolskiy@mentor.com> Cc: Thierry Reding <treding@nvidia.com> Cc: dri-devel@lists.freedesktop.org Cc: linux-kernel@vger.kernel.org ---
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
| |