drm/rockchip: dw_hdmi: Reset ddc bus when communication error

Signed-off-by: Algea Cao <algea.cao@rock-chips.com>
Change-Id: Ia397abda111f20aabff48ccb18ff6b228754d0e1
This commit is contained in:
Algea Cao
2021-12-28 15:19:39 +08:00
committed by Tao Huang
parent 9373efd7fa
commit 9f583cf19c
+18 -6
View File
@@ -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;
}