From b8f01149681f9f4b2ade03624b40c35c66f8702c Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 14 Mar 2023 17:16:56 +0800 Subject: [PATCH] drm: bridge: dw-hdmi: Fixed ddc error caused by plug out hdmi when reading edid Signed-off-by: Algea Cao Change-Id: Ie220584b5ae17822170bf761f699d8897caf9975 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 ++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 5d10966611e9..f77811dfdb7d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -420,18 +420,14 @@ static void repo_hpd_event(struct work_struct *p_work) if (hdmi->bridge.dev) { bool change; - void *data = hdmi->plat_data->phy_data; change = drm_helper_hpd_irq_event(hdmi->bridge.dev); - if (change) { - if (hdmi->plat_data->set_ddc_io) - hdmi->plat_data->set_ddc_io(data, hdmi->hpd_state); - if (hdmi->cec_adap->devnode.registered) - cec_queue_pin_hpd_event(hdmi->cec_adap, - hdmi->hpd_state, - ktime_get()); - } + if (change && hdmi->cec_adap && + hdmi->cec_adap->devnode.registered) + cec_queue_pin_hpd_event(hdmi->cec_adap, + hdmi->hpd_state, + ktime_get()); drm_bridge_hpd_notify(&hdmi->bridge, status); } } @@ -632,7 +628,11 @@ static int dw_hdmi_i2c_read(struct dw_hdmi *hdmi, while (retry > 0) { if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) { + void *data = hdmi->plat_data->phy_data; + dev_dbg(hdmi->dev, "hdmi disconnect, stop ddc read\n"); + if (hdmi->plat_data->set_ddc_io) + hdmi->plat_data->set_ddc_io(data, false); return -EPERM; } @@ -695,7 +695,11 @@ static int dw_hdmi_i2c_write(struct dw_hdmi *hdmi, while (retry > 0) { if (!(hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD)) { + void *data = hdmi->plat_data->phy_data; + dev_dbg(hdmi->dev, "hdmi disconnect, stop ddc write\n"); + if (hdmi->plat_data->set_ddc_io) + hdmi->plat_data->set_ddc_io(data, false); return -EPERM; } @@ -736,6 +740,7 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, struct dw_hdmi *hdmi = i2c_get_adapdata(adap); struct dw_hdmi_i2c *i2c = hdmi->i2c; u8 addr = msgs[0].addr; + void *data = hdmi->plat_data->phy_data; int i, ret = 0; if (addr == DDC_CI_ADDR) @@ -760,6 +765,9 @@ static int dw_hdmi_i2c_xfer(struct i2c_adapter *adap, mutex_lock(&i2c->lock); + if (hdmi->plat_data->set_ddc_io) + hdmi->plat_data->set_ddc_io(data, true); + hdmi_writeb(hdmi, 0, HDMI_I2CM_SOFTRSTZ); udelay(100); @@ -3924,6 +3932,7 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, struct drm_bridge_state *old_state) { struct dw_hdmi *hdmi = bridge->driver_private; + void *data = hdmi->plat_data->phy_data; mutex_lock(&hdmi->mutex); hdmi->disabled = true; @@ -3932,6 +3941,11 @@ static void dw_hdmi_bridge_atomic_disable(struct drm_bridge *bridge, dw_hdmi_update_power(hdmi); dw_hdmi_update_phy_mask(hdmi); mutex_unlock(&hdmi->mutex); + + mutex_lock(&hdmi->i2c->lock); + if (hdmi->plat_data->set_ddc_io) + hdmi->plat_data->set_ddc_io(data, false); + mutex_unlock(&hdmi->i2c->lock); } static void dw_hdmi_bridge_atomic_enable(struct drm_bridge *bridge,