From 9f583cf19c415c2fcf00a6784a89b76593532bda Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 28 Dec 2021 15:19:39 +0800 Subject: [PATCH] drm/rockchip: dw_hdmi: Reset ddc bus when communication error Signed-off-by: Algea Cao Change-Id: Ia397abda111f20aabff48ccb18ff6b228754d0e1 --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c | 24 +++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 5b73ab6c0c7b..cd8150b33bbb 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -689,12 +689,14 @@ static int dw_hdmi_i2c_read(struct dw_hdmi_qp *hdmi, stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); if (!stat) { dev_err(hdmi->dev, "i2c read time out!\n"); + hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); return -EAGAIN; } /* Check for error condition on the bus */ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { dev_err(hdmi->dev, "i2c read err!\n"); + hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); return -EIO; } @@ -734,12 +736,14 @@ static int dw_hdmi_i2c_write(struct dw_hdmi_qp *hdmi, stat = wait_for_completion_timeout(&i2c->cmp, HZ / 10); if (!stat) { dev_err(hdmi->dev, "i2c write time out!\n"); + hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); return -EAGAIN; } /* Check for error condition on the bus */ if (i2c->stat & I2CM_NACK_RCVD_IRQ) { dev_err(hdmi->dev, "i2c write nack!\n"); + hdmi_writel(hdmi, 0x01, I2CM_CONTROL0); return -EIO; } hdmi_modb(hdmi, 0, I2CM_WR_MASK, I2CM_INTERFACE_CONTROL0); @@ -1256,12 +1260,6 @@ static int hdmi_start_flt(struct dw_hdmi_qp *hdmi, u8 rate) u8 ffe_lv = 0; int i = 0, stat; - hdmi_modb(hdmi, SCDC_UPD_FLAGS_RD_IRQ, SCDC_UPD_FLAGS_RD_IRQ, - MAINUNIT_1_INT_MASK_N); - hdmi_modb(hdmi, SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, - SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, - SCDC_CONFIG0); - /* FLT_READY & FFE_LEVELS read */ for (i = 0; i < 20; i++) { drm_scdc_readb(hdmi->ddc, SCDC_STATUS_FLAGS_0, &val); @@ -1275,6 +1273,12 @@ static int hdmi_start_flt(struct dw_hdmi_qp *hdmi, u8 rate) return -EINVAL; } + hdmi_modb(hdmi, SCDC_UPD_FLAGS_RD_IRQ, SCDC_UPD_FLAGS_RD_IRQ, + MAINUNIT_1_INT_MASK_N); + hdmi_modb(hdmi, SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, + SCDC_UPD_FLAGS_POLL_EN | SCDC_UPD_FLAGS_AUTO_CLR, + SCDC_CONFIG0); + /* max ffe level 3 */ val = 3 << 4 | hdmi_set_frl_mask(rate); drm_scdc_writeb(hdmi->ddc, 0x31, val); @@ -1292,11 +1296,19 @@ static int hdmi_start_flt(struct dw_hdmi_qp *hdmi, u8 rate) stat = wait_for_completion_timeout(&hdmi->flt_cmp, HZ * 2); if (!stat) { dev_err(hdmi->dev, "wait lts3 finish time out\n"); + hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | + SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); + hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, + MAINUNIT_1_INT_MASK_N); return -EAGAIN; } if (!(hdmi->flt_intr & FLT_EXIT_TO_LTSP_IRQ)) { dev_err(hdmi->dev, "not to ltsp\n"); + hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_POLL_EN | + SCDC_UPD_FLAGS_AUTO_CLR, SCDC_CONFIG0); + hdmi_modb(hdmi, 0, SCDC_UPD_FLAGS_RD_IRQ, + MAINUNIT_1_INT_MASK_N); return -EINVAL; }