From: Yashas D <y-d@ti.com>
To: <jyri.sarha@iki.fi>, <tomi.valkeinen@ideasonboard.com>,
<maarten.lankhorst@linux.intel.com>, <mripard@kernel.org>,
<tzimmermann@suse.de>, <airlied@gmail.com>, <simona@ffwll.ch>,
<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>,
<y-d@ti.com>, <u-kumar1@ti.com>, <devarsht@ti.com>,
<s-jain1@ti.com>, <d-mittal@ti.com>, <b-padhi@ti.com>
Subject: [PATCH] drm/tidss: Fix synclost issue while disabling layer due to erratum i2097
Date: Tue, 30 Jun 2026 16:08:02 +0530 [thread overview]
Message-ID: <20260630103802.1853564-1-y-d@ti.com> (raw)
A gap beyond a frame duration for disabling the layer in overlay manager
and go bit setting on the corresponding video port may lead to SYNC_LOST.
Fix by moving the layer to the non-visible area and deferring the ENABLE=0
write, immediately before the GO bit, guaranteeing both occur within the
same frame window.
Link: https://www.ti.com/lit/pdf/sprz530
Signed-off-by: Yashas D <y-d@ti.com>
---
drivers/gpu/drm/tidss/tidss_dispc.c | 108 ++++++++++++++++++++++++++++
drivers/gpu/drm/tidss/tidss_dispc.h | 1 +
2 files changed, 109 insertions(+)
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
index 58d5eb033bdb..6cbf9dfc38b8 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.c
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c
@@ -38,6 +38,8 @@
#include "tidss_dispc_regs.h"
#include "tidss_scale_coefs.h"
+#define OVR_LAYER_MAX_POS(mask) FIELD_MAX(mask)
+
static const u16 tidss_k2g_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
[DSS_REVISION_OFF] = 0x00,
[DSS_SYSCONFIG_OFF] = 0x04,
@@ -467,6 +469,8 @@ struct dispc_device {
struct clk *fclk;
+ unsigned long fclk_rate;
+
bool is_enabled;
struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
@@ -477,6 +481,9 @@ struct dispc_device {
u32 memory_bandwidth_limit;
struct dispc_errata errata;
+
+ // WA for erratum i2097: OVR Layer Disable May Cause Sync Lost.
+ u32 pending_disable_layers[TIDSS_MAX_PORTS];
};
static void dispc_write(struct dispc_device *dispc, u16 reg, u32 val)
@@ -1128,6 +1135,12 @@ static void dispc_enable_am65x_oldi(struct dispc_device *dispc, u32 hw_videoport
void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
const struct drm_crtc_state *state)
{
+ /*
+ * WA for erratum i2097: clear any stale layer disable tracking
+ * state left over from the previous VP enable/disable cycle.
+ */
+ dispc->pending_disable_layers[hw_videoport] = 0;
+
const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
const struct dispc_bus_format *fmt;
const struct drm_display_mode *mode = &state->adjusted_mode;
@@ -1233,6 +1246,38 @@ void dispc_vp_go(struct dispc_device *dispc, u32 hw_videoport)
{
WARN_ON(VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL,
DISPC_VP_CONTROL_GOBIT_MASK));
+
+ if (dispc->errata.i2097 &&
+ dispc->pending_disable_layers[hw_videoport]) {
+ u32 layer;
+ u32 delay_ns;
+
+ /* WA for erratum i2097: set GO bit #1 to latch position
+ * changes into the DSS pipeline, wait 10 DSS functional clock
+ * cycles, then write ENABLE=0.
+ */
+ VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1,
+ DISPC_VP_CONTROL_GOBIT_MASK);
+
+ if (dispc->fclk_rate)
+ delay_ns = DIV_ROUND_UP_ULL((u64)10 * NSEC_PER_SEC,
+ dispc->fclk_rate);
+ else
+ delay_ns = 500;
+
+ ndelay(delay_ns);
+
+ for (layer = 0; layer < dispc->feat->num_vids; layer++) {
+ if (dispc->pending_disable_layers[hw_videoport] &
+ BIT(layer))
+ OVR_REG_FLD_MOD(dispc, hw_videoport,
+ DISPC_OVR_ATTRIBUTES(layer),
+ 0,
+ DISPC_OVR_ATTRIBUTES_ENABLE_MASK);
+ }
+ dispc->pending_disable_layers[hw_videoport] = 0;
+ }
+
VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1,
DISPC_VP_CONTROL_GOBIT_MASK);
}
@@ -1503,6 +1548,63 @@ void dispc_ovr_enable_layer(struct dispc_device *dispc,
if (dispc->feat->subrev == DISPC_K2G)
return;
+ if (dispc->errata.i2097 && !enable) {
+ /*
+ * WA for erratum i2097:
+ *
+ * Do not write ENABLE=0 directly. Instead move the layer to
+ * the non-visible area so it contributes no pixels.
+ *
+ * Position register layout differs per SoC:
+ * J721E : DISPC_OVR_ATTRIBUTES2, X[13:0], Y[29:16] (14-bit)
+ * Others: DISPC_OVR_ATTRIBUTES, X[17:6], Y[30:19] (12-bit)
+ */
+ switch (dispc->feat->subrev) {
+ case DISPC_J721E:
+ OVR_REG_FLD_MOD(dispc, hw_videoport,
+ DISPC_OVR_ATTRIBUTES2(layer),
+ OVR_LAYER_MAX_POS(DISPC_OVR_ATTRIBUTES2_POSX_MASK),
+ DISPC_OVR_ATTRIBUTES2_POSX_MASK);
+ OVR_REG_FLD_MOD(dispc, hw_videoport,
+ DISPC_OVR_ATTRIBUTES2(layer),
+ OVR_LAYER_MAX_POS(DISPC_OVR_ATTRIBUTES2_POSY_MASK),
+ DISPC_OVR_ATTRIBUTES2_POSY_MASK);
+ break;
+ case DISPC_AM62L:
+ OVR_REG_FLD_MOD(dispc, 0,
+ DISPC_OVR_ATTRIBUTES(0),
+ OVR_LAYER_MAX_POS(DISPC_OVR_ATTRIBUTES_POSX_MASK),
+ DISPC_OVR_ATTRIBUTES_POSX_MASK);
+ OVR_REG_FLD_MOD(dispc, 0,
+ DISPC_OVR_ATTRIBUTES(0),
+ OVR_LAYER_MAX_POS(DISPC_OVR_ATTRIBUTES_POSY_MASK),
+ DISPC_OVR_ATTRIBUTES_POSY_MASK);
+ break;
+ default:
+ OVR_REG_FLD_MOD(dispc, hw_videoport,
+ DISPC_OVR_ATTRIBUTES(layer),
+ OVR_LAYER_MAX_POS(DISPC_OVR_ATTRIBUTES_POSX_MASK),
+ DISPC_OVR_ATTRIBUTES_POSX_MASK);
+ OVR_REG_FLD_MOD(dispc, hw_videoport,
+ DISPC_OVR_ATTRIBUTES(layer),
+ OVR_LAYER_MAX_POS(DISPC_OVR_ATTRIBUTES_POSY_MASK),
+ DISPC_OVR_ATTRIBUTES_POSY_MASK);
+ break;
+ }
+
+ dispc->pending_disable_layers[hw_videoport] |= BIT(layer);
+ return;
+ }
+
+ if (dispc->errata.i2097 && enable) {
+ /*
+ * Layer being re-enabled: cancel any pending disable so
+ * dispc_vp_go() does not write ENABLE=0 after we have
+ * just written ENABLE=1 here.
+ */
+ dispc->pending_disable_layers[hw_videoport] &= ~BIT(layer);
+ }
+
OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
!!enable, DISPC_OVR_ATTRIBUTES_ENABLE_MASK);
}
@@ -2871,6 +2973,12 @@ static void dispc_init_errata(struct dispc_device *dispc)
dispc->errata.i2000 = true;
dev_info(dispc->dev, "WA for erratum i2000: YUV formats disabled\n");
}
+
+ if (dispc->feat->subrev != DISPC_K2G) {
+ dispc->errata.i2097 = true;
+ dev_info(dispc->dev,
+ "WA for erratum i2097: OVR layer disable uses non-visible area\n");
+ }
}
/*
diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h
index 739d211d0018..e2ce9fdf1279 100644
--- a/drivers/gpu/drm/tidss/tidss_dispc.h
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h
@@ -57,6 +57,7 @@ struct dispc_vid_info {
struct dispc_errata {
bool i2000; /* DSS Does Not Support YUV Pixel Data Formats */
+ bool i2097; /* OVR Layer Disable May Cause Sync Lost */
};
enum dispc_vp_bus_type {
--
2.34.1
next reply other threads:[~2026-06-30 10:39 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-30 10:38 Yashas D [this message]
2026-06-30 11:00 ` [PATCH] drm/tidss: Fix synclost issue while disabling layer due to erratum i2097 sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260630103802.1853564-1-y-d@ti.com \
--to=y-d@ti.com \
--cc=airlied@gmail.com \
--cc=b-padhi@ti.com \
--cc=d-mittal@ti.com \
--cc=devarsht@ti.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jyri.sarha@iki.fi \
--cc=linux-kernel@vger.kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=s-jain1@ti.com \
--cc=simona@ffwll.ch \
--cc=tomi.valkeinen@ideasonboard.com \
--cc=tzimmermann@suse.de \
--cc=u-kumar1@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.