* i.MX8MP: Fix HDMI LCDIF FIFO underruns
@ 2026-03-19 11:45 Krzysztof Hałasa
2026-03-20 2:39 ` Marek Vasut
0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Hałasa @ 2026-03-19 11:45 UTC (permalink / raw)
To: Marek Vasut, Stefan Agner
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, dri-devel, imx, linux-arm-kernel, linux-kernel
Running (and terminating) Weston on i.MX8MP sometimes produced black
or grey screens. The LCDIF3 INT_STATUS_D0 register showed a FIFO underrun:
32FC6024: 1000002
The PANIC0_THRES register was set to:
32FC6238: AA0154
which apparently meant low = 2736 bytes (0xAA * 16 + 16), high = 5456 bytes
(0x154 * 16 + 16).
With this patch (based on NXP's driver) the watermarks are only 16 bytes
higher (register values increased by 1) and the underruns are gone.
Tested on Solidrun Hummingboard Mate with a 1080p60 HDMI display.
Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl>
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -353,8 +353,8 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
u32 reg;
/* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
- writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
- FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
+ writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, DIV_ROUND_UP(1 * PANIC0_THRES_MAX, 3)) |
+ FIELD_PREP(PANIC0_THRES_HIGH_MASK, DIV_ROUND_UP(2 * PANIC0_THRES_MAX, 3)),
lcdif->base + LCDC_V8_PANIC0_THRES);
/*
--
Krzysztof "Chris" Hałasa
Sieć Badawcza Łukasiewicz
Przemysłowy Instytut Automatyki i Pomiarów PIAP
Al. Jerozolimskie 202, 02-486 Warszawa
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-19 11:45 i.MX8MP: Fix HDMI LCDIF FIFO underruns Krzysztof Hałasa
@ 2026-03-20 2:39 ` Marek Vasut
2026-03-20 8:04 ` Marco Felsch
0 siblings, 1 reply; 12+ messages in thread
From: Marek Vasut @ 2026-03-20 2:39 UTC (permalink / raw)
To: Krzysztof Hałasa, Stefan Agner, Liu Ying
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam, dri-devel, imx, linux-arm-kernel, linux-kernel
On 3/19/26 12:45 PM, Krzysztof Hałasa wrote:
> Running (and terminating) Weston on i.MX8MP sometimes produced black
> or grey screens. The LCDIF3 INT_STATUS_D0 register showed a FIFO underrun:
>
> 32FC6024: 1000002
>
> The PANIC0_THRES register was set to:
>
> 32FC6238: AA0154
>
> which apparently meant low = 2736 bytes (0xAA * 16 + 16), high = 5456 bytes
> (0x154 * 16 + 16).
>
> With this patch (based on NXP's driver) the watermarks are only 16 bytes
> higher (register values increased by 1) and the underruns are gone.
>
> Tested on Solidrun Hummingboard Mate with a 1080p60 HDMI display.
>
> Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl>
>
> --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> @@ -353,8 +353,8 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
> u32 reg;
>
> /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
> - writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
> - FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
> + writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, DIV_ROUND_UP(1 * PANIC0_THRES_MAX, 3)) |
> + FIELD_PREP(PANIC0_THRES_HIGH_MASK, DIV_ROUND_UP(2 * PANIC0_THRES_MAX, 3)),
I am starting to wonder, whether this should be configurable in DT,
because it seems there might be users that need to tweak the watermarks
one way or the other for different video outputs ?
+CC Liu
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-20 2:39 ` Marek Vasut
@ 2026-03-20 8:04 ` Marco Felsch
2026-03-20 9:25 ` Maxime Ripard
0 siblings, 1 reply; 12+ messages in thread
From: Marco Felsch @ 2026-03-20 8:04 UTC (permalink / raw)
To: Marek Vasut
Cc: Krzysztof Hałasa, Stefan Agner, Liu Ying, Simona Vetter, imx,
Fabio Estevam, Pengutronix Kernel Team, Maarten Lankhorst,
Sascha Hauer, Frank Li, linux-kernel, Maxime Ripard, dri-devel,
Thomas Zimmermann, David Airlie, linux-arm-kernel
On 26-03-20, Marek Vasut wrote:
> On 3/19/26 12:45 PM, Krzysztof Hałasa wrote:
> > Running (and terminating) Weston on i.MX8MP sometimes produced black
> > or grey screens. The LCDIF3 INT_STATUS_D0 register showed a FIFO underrun:
> >
> > 32FC6024: 1000002
> >
> > The PANIC0_THRES register was set to:
> >
> > 32FC6238: AA0154
> >
> > which apparently meant low = 2736 bytes (0xAA * 16 + 16), high = 5456 bytes
> > (0x154 * 16 + 16).
> >
> > With this patch (based on NXP's driver) the watermarks are only 16 bytes
> > higher (register values increased by 1) and the underruns are gone.
> >
> > Tested on Solidrun Hummingboard Mate with a 1080p60 HDMI display.
> >
> > Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl>
> >
> > --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > @@ -353,8 +353,8 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
> > u32 reg;
> > /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
> > - writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
> > - FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
> > + writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, DIV_ROUND_UP(1 * PANIC0_THRES_MAX, 3)) |
> > + FIELD_PREP(PANIC0_THRES_HIGH_MASK, DIV_ROUND_UP(2 * PANIC0_THRES_MAX, 3)),
>
> I am starting to wonder, whether this should be configurable in DT, because
> it seems there might be users that need to tweak the watermarks one way or
> the other for different video outputs ?
+1 to provide a override mechanism via DT.
Regards,
Marco
>
> +CC Liu
>
>
--
#gernperDu
#CallMeByMyFirstName
Pengutronix e.K. | |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-20 8:04 ` Marco Felsch
@ 2026-03-20 9:25 ` Maxime Ripard
2026-03-20 13:20 ` Krzysztof Hałasa
0 siblings, 1 reply; 12+ messages in thread
From: Maxime Ripard @ 2026-03-20 9:25 UTC (permalink / raw)
To: Marco Felsch
Cc: Marek Vasut, Krzysztof Hałasa, Stefan Agner, Liu Ying,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 1844 bytes --]
On Fri, Mar 20, 2026 at 09:04:17AM +0100, Marco Felsch wrote:
> On 26-03-20, Marek Vasut wrote:
> > On 3/19/26 12:45 PM, Krzysztof Hałasa wrote:
> > > Running (and terminating) Weston on i.MX8MP sometimes produced black
> > > or grey screens. The LCDIF3 INT_STATUS_D0 register showed a FIFO underrun:
> > >
> > > 32FC6024: 1000002
> > >
> > > The PANIC0_THRES register was set to:
> > >
> > > 32FC6238: AA0154
> > >
> > > which apparently meant low = 2736 bytes (0xAA * 16 + 16), high = 5456 bytes
> > > (0x154 * 16 + 16).
> > >
> > > With this patch (based on NXP's driver) the watermarks are only 16 bytes
> > > higher (register values increased by 1) and the underruns are gone.
> > >
> > > Tested on Solidrun Hummingboard Mate with a 1080p60 HDMI display.
> > >
> > > Signed-off-by: Krzysztof Hałasa <khalasa@piap.pl>
> > >
> > > --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > > +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> > > @@ -353,8 +353,8 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
> > > u32 reg;
> > > /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
> > > - writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
> > > - FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
> > > + writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, DIV_ROUND_UP(1 * PANIC0_THRES_MAX, 3)) |
> > > + FIELD_PREP(PANIC0_THRES_HIGH_MASK, DIV_ROUND_UP(2 * PANIC0_THRES_MAX, 3)),
> >
> > I am starting to wonder, whether this should be configurable in DT, because
> > it seems there might be users that need to tweak the watermarks one way or
> > the other for different video outputs ?
>
> +1 to provide a override mechanism via DT.
If this is related to the output resolution, the DT is the last place
you should deal with this.
Maxime
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 273 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-20 9:25 ` Maxime Ripard
@ 2026-03-20 13:20 ` Krzysztof Hałasa
2026-03-23 8:18 ` Liu Ying
0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Hałasa @ 2026-03-20 13:20 UTC (permalink / raw)
To: Maxime Ripard
Cc: Marco Felsch, Marek Vasut, Stefan Agner, Liu Ying, Simona Vetter,
imx, Fabio Estevam, Pengutronix Kernel Team, Maarten Lankhorst,
Sascha Hauer, Frank Li, linux-kernel, dri-devel,
Thomas Zimmermann, David Airlie, linux-arm-kernel
Maxime Ripard <mripard@kernel.org> writes:
>> > > - writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
>> > > - FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
>> > > + writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, DIV_ROUND_UP(1 * PANIC0_THRES_MAX, 3)) |
>> > > + FIELD_PREP(PANIC0_THRES_HIGH_MASK, DIV_ROUND_UP(2 * PANIC0_THRES_MAX, 3)),
> If this is related to the output resolution, the DT is the last place
> you should deal with this.
Well... just tested (v6.19 + patch) with 2160p30 and, surprise surprise,
it doesn't work for like 10% of the time. I.e., the display may freeze
at weston start and/or shutdown time, but otherwise works:
v6.19 (frozen screen while starting weston, same display, the patch
applied):
32FC6000: 2 2 2 2
32FC6010: 80000000 8700F00 12800B0 480008
32FC6020: A0058 1000007 0
32FC6030: 1 1
32FC6200: 8700F00 223C00 EF000000
32FC6210: 0 89000000 1
32FC6220: 0 0 0 0
32FC6230: 0 0 AB0155
OTOH NXP's 6.6.23 works all the time:
NCP v6.6.23 (a different i.MX8MP):
32FC6000: A A A A
32FC6010: 80000000 8700F00 12800B0 480008
32FC6020: A0058 10005 0
32FC6030: 1 1
32FC6200: 8700F00 A23C00 97C00000
32FC6210: 0 89000000 1
32FC6220: 0 0 0 0
32FC6230: 0 0 AB0155
32FC600x 2 vs. A is pixel clock inversion.
32FC6208 is config P_SIZE, T_SIZE + pitch.
More tests after weekend.
--
Krzysztof "Chris" Hałasa
Sieć Badawcza Łukasiewicz
Przemysłowy Instytut Automatyki i Pomiarów PIAP
Al. Jerozolimskie 202, 02-486 Warszawa
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-20 13:20 ` Krzysztof Hałasa
@ 2026-03-23 8:18 ` Liu Ying
2026-03-23 12:54 ` Krzysztof Hałasa
2026-03-25 12:40 ` Krzysztof Hałasa
0 siblings, 2 replies; 12+ messages in thread
From: Liu Ying @ 2026-03-23 8:18 UTC (permalink / raw)
To: Krzysztof Hałasa, Maxime Ripard
Cc: Marco Felsch, Marek Vasut, Stefan Agner, Simona Vetter, imx,
Fabio Estevam, Pengutronix Kernel Team, Maarten Lankhorst,
Sascha Hauer, Frank Li, linux-kernel, dri-devel,
Thomas Zimmermann, David Airlie, linux-arm-kernel, Lucas Stach
On Fri, Mar 20, 2026 at 02:20:15PM +0100, Krzysztof Hałasa wrote:
> Maxime Ripard <mripard@kernel.org> writes:
>
>>>>> - writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
>>>>> - FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
>>>>> + writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, DIV_ROUND_UP(1 * PANIC0_THRES_MAX, 3)) |
>>>>> + FIELD_PREP(PANIC0_THRES_HIGH_MASK, DIV_ROUND_UP(2 * PANIC0_THRES_MAX, 3)),
>
>> If this is related to the output resolution, the DT is the last place
>> you should deal with this.
>
> Well... just tested (v6.19 + patch) with 2160p30 and, surprise surprise,
> it doesn't work for like 10% of the time. I.e., the display may freeze
> at weston start and/or shutdown time, but otherwise works:
If you may use a display mode with low resolution, say 640x480p60, and
the issue still happens, then I bet it's not related to the panic
threshold settings, but more likely related to KMS detail control seqeunce.
This reminds me that Lucas had a patch series[1] to try to fix the
sequence, but it seems that it didn't fix i.MX93 LCDIF according to [2]
hence no landing.
[1] https://lore.kernel.org/all/20230928113629.103188-1-l.stach@pengutronix.de/#t
[2] https://lore.kernel.org/all/AM7PR04MB7046FF021B8BA46EFB758BA098CFA@AM7PR04MB7046.eurprd04.prod.outlook.com/
Cc'ing Lucas.
>
> v6.19 (frozen screen while starting weston, same display, the patch
> applied):
> 32FC6000: 2 2 2 2
> 32FC6010: 80000000 8700F00 12800B0 480008
> 32FC6020: A0058 1000007 0
> 32FC6030: 1 1
> 32FC6200: 8700F00 223C00 EF000000
> 32FC6210: 0 89000000 1
> 32FC6220: 0 0 0 0
> 32FC6230: 0 0 AB0155
>
> OTOH NXP's 6.6.23 works all the time:
> NCP v6.6.23 (a different i.MX8MP):
> 32FC6000: A A A A
> 32FC6010: 80000000 8700F00 12800B0 480008
> 32FC6020: A0058 10005 0
> 32FC6030: 1 1
> 32FC6200: 8700F00 A23C00 97C00000
> 32FC6210: 0 89000000 1
> 32FC6220: 0 0 0 0
> 32FC6230: 0 0 AB0155
A newer downstream kernel with newer kernel version dumps reg@32FC6230 as
0x01000180 instead of 0xAB0155. Note that this downstream kernel sets
lcdif3 thresholds in DT:
&lcdif3 {
status = "okay";
thres-low = <1 2>; /* (FIFO * 1 / 2) */
thres-high = <3 4>; /* (FIFO * 3 / 4) */
};
I didn't tune/determine the threshold settings for downstream kernel, so what
could I say? Maybe, align upstream kernel with downstream kernel.
>
> 32FC600x 2 vs. A is pixel clock inversion.
> 32FC6208 is config P_SIZE, T_SIZE + pitch.
>
> More tests after weekend.
--
Regards,
Liu Ying
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-23 8:18 ` Liu Ying
@ 2026-03-23 12:54 ` Krzysztof Hałasa
2026-03-30 16:20 ` Paul Kocialkowski
2026-03-25 12:40 ` Krzysztof Hałasa
1 sibling, 1 reply; 12+ messages in thread
From: Krzysztof Hałasa @ 2026-03-23 12:54 UTC (permalink / raw)
To: Liu Ying
Cc: Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel,
Lucas Stach
Hi Liu,
Liu Ying <victor.liu@nxp.com> writes:
> If you may use a display mode with low resolution, say 640x480p60, and
> the issue still happens, then I bet it's not related to the panic
> threshold settings, but more likely related to KMS detail control seqeunce.
> This reminds me that Lucas had a patch series[1] to try to fix the
> sequence, but it seems that it didn't fix i.MX93 LCDIF according to [2]
> hence no landing.
It seems it depends on resolution: at 1080p60 with the DIV_ROUND_UP
(thresholds increased by 1) it seems to work fine. At 2160p30 (twice the
clock) there are frequent underruns. Now with thresholds increased to
2/4 and 3/4, weston started fine 10/10, while shutdowns were 8/10.
4/6 and 5/6 made it worse, though.
I don't know now. I will try to investigate a bit more tomorrow.
Perhaps the sequence of register writes could be better, indeed.
The following doesn't fix it for me either:
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -358,34 +358,27 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
writel(INT_ENABLE_D1_PLANE_PANIC_EN,
lcdif->base + LCDC_V8_INT_ENABLE_D1);
- reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
- reg |= DISP_PARA_DISP_ON;
- writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
-
reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
reg |= CTRLDESCL0_5_EN;
writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
+
+ reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
+ reg |= DISP_PARA_DISP_ON;
+ writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
}
--
Krzysztof "Chris" Hałasa
Sieć Badawcza Łukasiewicz
Przemysłowy Instytut Automatyki i Pomiarów PIAP
Al. Jerozolimskie 202, 02-486 Warszawa
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-23 8:18 ` Liu Ying
2026-03-23 12:54 ` Krzysztof Hałasa
@ 2026-03-25 12:40 ` Krzysztof Hałasa
2026-03-30 16:09 ` Paul Kocialkowski
1 sibling, 1 reply; 12+ messages in thread
From: Krzysztof Hałasa @ 2026-03-25 12:40 UTC (permalink / raw)
To: Liu Ying
Cc: Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel,
Lucas Stach
Hi,
maybe I don't understand this, but... added a bunch of printk()s:
static void dump(struct lcdif_drm_private *lcdif, const char *func, unsigned line)
{
uint32_t d1 = readl(lcdif->base + LCDC_V8_INT_STATUS_D1);
printk(KERN_DEBUG "%s[%u]\n", func, line);
printk(KERN_DEBUG "CTRL %08X PARA %08X %08X %08X %08X %08X\n",
readl(lcdif->base + LCDC_V8_CTRL),
readl(lcdif->base + LCDC_V8_DISP_PARA),
readl(lcdif->base + LCDC_V8_DISP_SIZE),
readl(lcdif->base + LCDC_V8_HSYN_PARA),
readl(lcdif->base + LCDC_V8_VSYN_PARA),
readl(lcdif->base + LCDC_V8_VSYN_HSYN_WIDTH));
printk(KERN_DEBUG "D0 %08X %08X D1 %08X(C) %08X\n",
readl(lcdif->base + LCDC_V8_INT_STATUS_D0),
readl(lcdif->base + LCDC_V8_INT_ENABLE_D0),
d1,
readl(lcdif->base + LCDC_V8_INT_ENABLE_D1));
printk(KERN_DEBUG "DESC %08X %08X %08X %08X %08X\n",
readl(lcdif->base + LCDC_V8_CTRLDESCL0_1),
readl(lcdif->base + LCDC_V8_CTRLDESCL0_3),
readl(lcdif->base + LCDC_V8_CTRLDESCL_LOW0_4),
readl(lcdif->base + LCDC_V8_CTRLDESCL_HIGH0_4),
readl(lcdif->base + LCDC_V8_CTRLDESCL0_5));
if (d1)
writel(d1, lcdif->base + LCDC_V8_INT_STATUS_D1); // clear D1 status
}
(C) after LCDC_V8_INT_STATUS_D1 value means I clear it after read. It's
the single PANIC bit, "write 1 to clear".
LCDIFV3_PANIC0_THRES is 0x15501AA, but 2/4 and 3/4 didn't fix it either
(completely at least). 2160p30. Also added the undocumented
CTRLDESCL0_3_STATE_CLEAR_VSYNC bit as in NXP's driver (clearing FIFO on
VSYNC).
Normal start (before Weston):
4.943 lcdif_reset_block[432]
4.943 CTRL 80000000 PARA 00000000 00000000 00030003 00030003 00030003 <<<<< SW_RESET
4.943 D0 00000000 00000000 D1 00000000(C) 00000000
4.943 DESC 00000000 00000000 00000000 00000000 00000000
4.943 lcdif_reset_block[437]
4.943 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
4.943 D0 00000000 00000000 D1 00000000(C) 00000000
4.943 DESC 00000000 00000000 00000000 00000000 00000000
4.943 lcdif_set_formats[197]
4.943 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
4.943 D0 00000000 00000000 D1 00000000(C) 00000000
4.943 DESC 00000000 00000000 00000000 00000000 00000000
4.943 lcdif_set_formats[320]
4.943 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
4.943 D0 00000000 00000000 D1 00000000(C) 00000000
4.943 DESC 00000000 00000000 00000000 00000000 09000000
4.943 lcdif_set_mode[340]
4.943 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
4.943 D0 00000000 00000000 D1 00000000(C) 00000000
4.943 DESC 00000000 00000000 00000000 00000000 09000000
4.943 lcdif_enable_controller[382]
4.943 CTRL 00000002 PARA 00000000 08700F00 012800B0 00480008 000A0058
4.943 D0 00000000 00000000 D1 00000000(C) 00000000
4.943 DESC 08700F00 00A23C00 ED000000 00000000 09000000
4.948 lcdif_enable_controller[402]
4.948 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.949 D0 00000000 00000000 D1 00000000(C) 00000001
4.949 DESC 08700F00 00A23C00 ED000000 00000000 89000000 <<<<< DMA_EN
I don't know what exactly happens at this point, the DMA starts and the
CRTC also starts scanning right away? No underrun follows. Not even
"panic" indication:
4.949 lcdif_crtc_atomic_enable[604]
4.950 lcdif_plane_primary_atomic_update[746]
4.951 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.951 D0 00000000 00000000 D1 00000000(C) 00000001
4.951 DESC 08700F00 00A23C00 ED000000 00000000 89000000
4.956 lcdif_plane_primary_atomic_update[755]
4.956 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.956 D0 00000000 00000000 D1 00000000(C) 00000001
4.956 DESC 08700F00 00A23C00 ED000000 00000000 89000000
4.956 lcdif_crtc_atomic_flush[554]
4.956 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.956 D0 00000000 00000000 D1 00000000(C) 00000001
4.957 DESC 08700F00 00A23C00 ED000000 00000000 89000000
4.957 lcdif_crtc_atomic_flush[558]
4.957 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.957 D0 00000000 00000000 D1 00000000(C) 00000001
4.957 DESC 08700F00 00A23C00 ED000000 00000000 C9000000 <<<<< SHADOWS
^^^ The code programs the CRTC to update DMA registers (only?), I guess
mostly the frame buffer address, on the next frame end / start /
whatever event.
4.957 lcdif_crtc_enable_vblank[678]
4.957 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.957 D0 00000000 00000000 D1 00000000(C) 00000001
4.957 DESC 08700F00 00A23C00 ED000000 00000000 C9000000 <<<<< SHADOWS
4.962 lcdif_crtc_enable_vblank[683]
4.962 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.962 D0 00000000 00000004 D1 00000000(C) 00000001
4.962 DESC 08700F00 00A23C00 ED000000 00000000 C9000000 <<<<< SHADOWS
4.963 lcdif_crtc_atomic_flush[572]
if the frame started at 4.948 - 4.949, the next one is due at ca. 4.982
(30 Hz). VSync should start not sooner than 4.980 (32.0 ms).
4.977 lcdif_crtc_atomic_destroy_state[632]
4.977 Console: switching to colour frame buffer device 240x67
4.977 lcdif_crtc_atomic_duplicate_state[661]
4.977 lcdif_crtc_atomic_check[480]
4.977 lcdif_crtc_atomic_check[542]
4.977 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.977 D0 00000001 00000004 D1 00000000(C) 00000001 <<<<< VSYNC
4.978 DESC 08700F00 00A23C00 ED000000 00000000 89000000
^^^ Here the "update shadow" bit is (self) cleared, so I think the frame
has ended (or the next one started), and a new one has started (or is
about to). No underrun. This is not an IRQ. Interestingly, it's not
4.980 yet.
4.978 lcdif_crtc_atomic_check[543]
4.978 lcdif_plane_primary_atomic_update[746]
4.978 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.978 D0 00000001 00000004 D1 00000000(C) 00000001
4.978 DESC 08700F00 00A23C00 ED000000 00000000 89000000
4.985 lcdif_plane_primary_atomic_update[755]
4.985 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
4.985 D0 00000001 00000004 D1 00000000(C) 00000001
4.985 DESC 08700F00 00A23C00 ED000000 00000000 89000000
At this point, the new frame definitely has started (7+ ms since VSYNC).
Now starting Weston:
...
34.655 CTRL 80000000 PARA 00000000 00000000 00030003 00030003 00030003 <<<<< SW_RESET
34.655 D0 00000000 00000000 D1 00000000(C) 00000000
34.655 DESC 00000000 00000000 00000000 00000000 00000000
34.655 lcdif_reset_block[437]
34.655 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
34.655 D0 00000000 00000000 D1 00000000(C) 00000000
34.655 DESC 00000000 00000000 00000000 00000000 00000000
34.655 lcdif_set_formats[197]
34.655 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
34.655 D0 00000000 00000000 D1 00000000(C) 00000000
34.655 DESC 00000000 00000000 00000000 00000000 00000000
34.655 lcdif_set_formats[320]
34.655 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
34.655 D0 00000000 00000000 D1 00000000(C) 00000000
34.655 DESC 00000000 00000000 00000000 00000000 09000000
34.655 lcdif_set_mode[340]
34.655 CTRL 00000000 PARA 00000000 00000000 00030003 00030003 00030003
34.655 D0 00000000 00000000 D1 00000000(C) 00000000
34.655 DESC 00000000 00000000 00000000 00000000 09000000
34.655 lcdif_enable_controller[382]
34.655 CTRL 00000002 PARA 00000000 08700F00 012800B0 00480008 000A0058
34.655 D0 00000000 00000000 D1 00000000(C) 00000000
34.655 DESC 08700F00 00A23C00 EF000000 00000000 09000000
34.660 lcdif_enable_controller[402]
34.660 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.660 D0 00000000 00000000 D1 00000000(C) 00000001
34.660 DESC 08700F00 00A23C00 EF000000 00000000 89000000 <<<<< DMA_EN
As above, the only difference is frame buffer address.
34.660 lcdif_crtc_atomic_enable[604]
34.661 lcdif_plane_primary_atomic_update[746]
34.661 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.661 D0 00000000 00000000 D1 00000000(C) 00000001
34.661 DESC 08700F00 00A23C00 EF000000 00000000 89000000
34.666 lcdif_plane_primary_atomic_update[755]
34.666 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.666 D0 00000000 00000000 D1 00000000(C) 00000001
34.667 DESC 08700F00 00A23C00 EF000000 00000000 89000000
34.667 lcdif_crtc_atomic_flush[554]
34.667 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.667 D0 00000000 00000000 D1 00000000(C) 00000001
34.667 DESC 08700F00 00A23C00 EF000000 00000000 89000000
34.667 lcdif_crtc_atomic_flush[558]
34.667 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.667 D0 00000000 00000000 D1 00000000(C) 00000001
34.667 DESC 08700F00 00A23C00 EF000000 00000000 C9000000 <<<<< SHADOWS
The DMA registers are to be updated on the next VSYNC.
34.667 lcdif_crtc_enable_vblank[678]
34.667 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.667 D0 00000000 00000000 D1 00000000(C) 00000001
34.667 DESC 08700F00 00A23C00 EF000000 00000000 C9000000 <<<<< SHADOWS
34.672 lcdif_crtc_enable_vblank[683]
34.672 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
34.672 D0 00000000 00000004 D1 00000000(C) 00000001
34.672 DESC 08700F00 00A23C00 EF000000 00000000 C9000000 <<<<< SHADOWS
34.689 lcdif_crtc_atomic_destroy_state[632]
35.482 lcdif_crtc_atomic_duplicate_state[661]
35.482 lcdif_crtc_atomic_check[480]
35.482 lcdif_crtc_atomic_check[542]
35.482 CTRL 00000002 PARA 80000000 08700F00 012800B0 00480008 000A0058
35.482 D0 01000002 00000004 D1 00000001(C) 00000001 <<<<< UNDERRUN
35.482 DESC 08700F00 00A23C00 EF000000 00000000 89000000
No VSYNC bit (though shadow updates happen on VSYNC), PANIC registered,
and UNDERRUN.
Why did the first (boot) sequence result in success and this second one
in failure? This is somehow reproducible.
Interestingly, Weston usually starts fine in subsequent launches.
How is this first (actually second - after the first VSYNC) frame
different from all the others? Maybe we're programming UPDATE_SHADOW
after the actual start of blanking period, but before DE, so it has no
chance to reload registers, yet the DMA is somehow not ready?
The manual (LCDIF display control Register (CTRL)) suggests that the DMA
(with present settings) starts to fetch FB data at the end of the
previous active video pixel time (DE and pixel data going inactive):
fetch_start_option (bits 9-8): Indicates when to start fetching for new
frame. This signals also decide the shadow load, fifo clear time
00b - fetch start as soon as FPV begins(as the end of the data_enable).
This should leave a lot of time to fill the FIFO (before the next DE),
shouldn't it?
297 MHz pixclk, 3840x2160, 30 Hz, H back porch 296 pixclks, Vfp 176,
V back porch 72 lines, Hfp 8 lines, VSYNC 10 lines, HSYNC 88 pixclks.
HTotal = 4400 pixels which makes Vactive time = 4400 * 2160/297e6 =
32 ms, with the remaining 1.3333 ms for all the V sync stuff.
--
Krzysztof "Chris" Hałasa
Sieć Badawcza Łukasiewicz
Przemysłowy Instytut Automatyki i Pomiarów PIAP
Al. Jerozolimskie 202, 02-486 Warszawa
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-25 12:40 ` Krzysztof Hałasa
@ 2026-03-30 16:09 ` Paul Kocialkowski
2026-03-30 16:44 ` Lucas Stach
0 siblings, 1 reply; 12+ messages in thread
From: Paul Kocialkowski @ 2026-03-30 16:09 UTC (permalink / raw)
To: Krzysztof Hałasa
Cc: Liu Ying, Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel,
Lucas Stach
[-- Attachment #1: Type: text/plain, Size: 3498 bytes --]
Hi folks,
On Wed 25 Mar 26, 13:40, Krzysztof Hałasa wrote:
> Why did the first (boot) sequence result in success and this second one
> in failure? This is somehow reproducible.
I've been seeing the same issue that is described in this thread when driving
a regular 1080p@60 monitor, which shows a solid color background with a pixel
from the previous frame when reconfiguring the mode from time to time.
When that happens, I see the lcdif fifo underrun/empty status until a new mode
is applied, which often resolves the situation. This situation never happens
with the downstream nxp bsp driver.
After weeks of investigation I finally narrowed it down to a part of the nxp
original code that is missing in the upstream driver:
https://github.com/phytec/linux-phytec-imx/blob/v6.6.23-2.0.0-phy/drivers/gpu/imx/lcdifv3/lcdifv3-common.c#L492
A big old sleep that waits for the DMA engine to finish handling the current
frame before it is disabled. When this delay is not respected, there seems to
be "unlucky" times when disabling the DMA engine too early will confuse the
unit and make it unable to resume proper operation later.
It is a bit surprising that the issue is not actually related to configuring
the display engine but to disabling it. This is why the first mode set always
works but subsequentil ones might fail. The crtc is essentially disabled and
re-enabled each time a new mode is applied.
Adding the sleep solves the issue on my side and all mode sets now work
reliably. It does add a delay before returning to userspace when configuring
a new mode, but it seems legitimate to me if the underlying hardware is still
in-flight. I'm also unsure if it would apply to an async atomic commit.
I will send a patch adding the delay and the undocumented fifo clear
bit that was discovered in this thread too.
All the best,
Paul
Perhaps there is a more elegant way to handle this
> Interestingly, Weston usually starts fine in subsequent launches.
>
> How is this first (actually second - after the first VSYNC) frame
> different from all the others? Maybe we're programming UPDATE_SHADOW
> after the actual start of blanking period, but before DE, so it has no
> chance to reload registers, yet the DMA is somehow not ready?
>
> The manual (LCDIF display control Register (CTRL)) suggests that the DMA
> (with present settings) starts to fetch FB data at the end of the
> previous active video pixel time (DE and pixel data going inactive):
> fetch_start_option (bits 9-8): Indicates when to start fetching for new
> frame. This signals also decide the shadow load, fifo clear time
> 00b - fetch start as soon as FPV begins(as the end of the data_enable).
>
> This should leave a lot of time to fill the FIFO (before the next DE),
> shouldn't it?
>
> 297 MHz pixclk, 3840x2160, 30 Hz, H back porch 296 pixclks, Vfp 176,
> V back porch 72 lines, Hfp 8 lines, VSYNC 10 lines, HSYNC 88 pixclks.
> HTotal = 4400 pixels which makes Vactive time = 4400 * 2160/297e6 =
> 32 ms, with the remaining 1.3333 ms for all the V sync stuff.
> --
> Krzysztof "Chris" Hałasa
>
> Sieć Badawcza Łukasiewicz
> Przemysłowy Instytut Automatyki i Pomiarów PIAP
> Al. Jerozolimskie 202, 02-486 Warszawa
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-23 12:54 ` Krzysztof Hałasa
@ 2026-03-30 16:20 ` Paul Kocialkowski
0 siblings, 0 replies; 12+ messages in thread
From: Paul Kocialkowski @ 2026-03-30 16:20 UTC (permalink / raw)
To: Krzysztof Hałasa
Cc: Liu Ying, Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel,
Lucas Stach
[-- Attachment #1: Type: text/plain, Size: 3187 bytes --]
Hi,
On Mon 23 Mar 26, 13:54, Krzysztof Hałasa wrote:
> Liu Ying <victor.liu@nxp.com> writes:
> > If you may use a display mode with low resolution, say 640x480p60, and
> > the issue still happens, then I bet it's not related to the panic
> > threshold settings, but more likely related to KMS detail control seqeunce.
I've also seen the same behavior. The NoC panic thresholds are meant to
temporarily increase the NoC master priority if the FIFOs are not able to
fetch data in time because too much data is moving on the NoC interconnect
and the display engine may be starved and fail to fetch data in time for
scanout.
The fact that our issue also happens with low sizes means that NoC access is
probably not the bottleneck that causes the FIFO errors and that tweaking the
thresholds probably has no effect. I've also made my experiments with pretty
much nothing running on the system, so the NoC has no reason to be busy.
One issue I had with this issue is that it sometimes feels like certain changes
make the issue less frequent, but it is often just variability due to the small
numbers of tries.
It's true however that the nxp bsp does use different thereshold values for
lcdif3, which are probably tweaked for specific use cases with high load on
the interconnect. But I'm not sure it's very important to have them in mainline
for now.
All the best,
Paul
> > This reminds me that Lucas had a patch series[1] to try to fix the
> > sequence, but it seems that it didn't fix i.MX93 LCDIF according to [2]
> > hence no landing.
>
> It seems it depends on resolution: at 1080p60 with the DIV_ROUND_UP
> (thresholds increased by 1) it seems to work fine. At 2160p30 (twice the
> clock) there are frequent underruns. Now with thresholds increased to
> 2/4 and 3/4, weston started fine 10/10, while shutdowns were 8/10.
> 4/6 and 5/6 made it worse, though.
>
> I don't know now. I will try to investigate a bit more tomorrow.
> Perhaps the sequence of register writes could be better, indeed.
>
> The following doesn't fix it for me either:
> --- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
> +++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
> @@ -358,34 +358,27 @@ static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
> writel(INT_ENABLE_D1_PLANE_PANIC_EN,
> lcdif->base + LCDC_V8_INT_ENABLE_D1);
>
> - reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
> - reg |= DISP_PARA_DISP_ON;
> - writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
> -
> reg = readl(lcdif->base + LCDC_V8_CTRLDESCL0_5);
> reg |= CTRLDESCL0_5_EN;
> writel(reg, lcdif->base + LCDC_V8_CTRLDESCL0_5);
> +
> + reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
> + reg |= DISP_PARA_DISP_ON;
> + writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
> }
>
>
> --
> Krzysztof "Chris" Hałasa
>
> Sieć Badawcza Łukasiewicz
> Przemysłowy Instytut Automatyki i Pomiarów PIAP
> Al. Jerozolimskie 202, 02-486 Warszawa
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-30 16:09 ` Paul Kocialkowski
@ 2026-03-30 16:44 ` Lucas Stach
2026-03-30 21:16 ` Paul Kocialkowski
0 siblings, 1 reply; 12+ messages in thread
From: Lucas Stach @ 2026-03-30 16:44 UTC (permalink / raw)
To: Paul Kocialkowski, Krzysztof Hałasa
Cc: Liu Ying, Maxime Ripard, Marco Felsch, Marek Vasut, Stefan Agner,
Simona Vetter, imx, Fabio Estevam, Pengutronix Kernel Team,
Maarten Lankhorst, Sascha Hauer, Frank Li, linux-kernel,
dri-devel, Thomas Zimmermann, David Airlie, linux-arm-kernel
Hi Paul,
Am Montag, dem 30.03.2026 um 18:09 +0200 schrieb Paul Kocialkowski:
> Hi folks,
>
> On Wed 25 Mar 26, 13:40, Krzysztof Hałasa wrote:
> > Why did the first (boot) sequence result in success and this second one
> > in failure? This is somehow reproducible.
>
> I've been seeing the same issue that is described in this thread when driving
> a regular 1080p@60 monitor, which shows a solid color background with a pixel
> from the previous frame when reconfiguring the mode from time to time.
>
> When that happens, I see the lcdif fifo underrun/empty status until a new mode
> is applied, which often resolves the situation. This situation never happens
> with the downstream nxp bsp driver.
>
> After weeks of investigation I finally narrowed it down to a part of the nxp
> original code that is missing in the upstream driver:
> https://github.com/phytec/linux-phytec-imx/blob/v6.6.23-2.0.0-phy/drivers/gpu/imx/lcdifv3/lcdifv3-common.c#L492
>
Thanks for tracking this down! It was also on my list of things to look
at.
> A big old sleep that waits for the DMA engine to finish handling the current
> frame before it is disabled. When this delay is not respected, there seems to
> be "unlucky" times when disabling the DMA engine too early will confuse the
> unit and make it unable to resume proper operation later.
>
I think we can be a bit more clever than a indiscriminate sleep. If we
set the shadow load enable bit in the disable sequence, we should be
able to wait for this bit to be cleared by the hardware. All the DMA
parameters (presumably including the enable state) should be applied by
the hardware when this bit is cleared.
I guess the read_poll_timeout in lcdif_disable_controller() was
supposed to do exactly that wait, but as it was actually copied from
the mxsfb driver, it's not working as intended. It's my understanding
that the old lcdif HW only cleared the enable bit once it is actually
done, but on the lcdifv3 on i.MX8MP those states are double buffered,
so the bit in the register would be cleared instantaneously, rendering
the wait in the current code a no-op. The only reliable indicator to
see if the HW has updated it's internal state is to set the shadow load
enable bit and wait for it to be cleared.
> It is a bit surprising that the issue is not actually related to configuring
> the display engine but to disabling it. This is why the first mode set always
> works but subsequentil ones might fail. The crtc is essentially disabled and
> re-enabled each time a new mode is applied.
>
> Adding the sleep solves the issue on my side and all mode sets now work
> reliably. It does add a delay before returning to userspace when configuring
> a new mode, but it seems legitimate to me if the underlying hardware is still
> in-flight. I'm also unsure if it would apply to an async atomic commit.
>
This hardware doesn't support async commits. All DMA state changes are
applied during vblank when the shadow load enable bit is set.
Regards,
Lucas
> I will send a patch adding the delay and the undocumented fifo clear
> bit that was discovered in this thread too.
>
> All the best,
>
> Paul
>
> Perhaps there is a more elegant way to handle this
>
>
> > Interestingly, Weston usually starts fine in subsequent launches.
> >
> > How is this first (actually second - after the first VSYNC) frame
> > different from all the others? Maybe we're programming UPDATE_SHADOW
> > after the actual start of blanking period, but before DE, so it has no
> > chance to reload registers, yet the DMA is somehow not ready?
> >
> > The manual (LCDIF display control Register (CTRL)) suggests that the DMA
> > (with present settings) starts to fetch FB data at the end of the
> > previous active video pixel time (DE and pixel data going inactive):
> > fetch_start_option (bits 9-8): Indicates when to start fetching for new
> > frame. This signals also decide the shadow load, fifo clear time
> > 00b - fetch start as soon as FPV begins(as the end of the data_enable).
> >
> > This should leave a lot of time to fill the FIFO (before the next DE),
> > shouldn't it?
> >
> > 297 MHz pixclk, 3840x2160, 30 Hz, H back porch 296 pixclks, Vfp 176,
> > V back porch 72 lines, Hfp 8 lines, VSYNC 10 lines, HSYNC 88 pixclks.
> > HTotal = 4400 pixels which makes Vactive time = 4400 * 2160/297e6 =
> > 32 ms, with the remaining 1.3333 ms for all the V sync stuff.
> > --
> > Krzysztof "Chris" Hałasa
> >
> > Sieć Badawcza Łukasiewicz
> > Przemysłowy Instytut Automatyki i Pomiarów PIAP
> > Al. Jerozolimskie 202, 02-486 Warszawa
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: i.MX8MP: Fix HDMI LCDIF FIFO underruns
2026-03-30 16:44 ` Lucas Stach
@ 2026-03-30 21:16 ` Paul Kocialkowski
0 siblings, 0 replies; 12+ messages in thread
From: Paul Kocialkowski @ 2026-03-30 21:16 UTC (permalink / raw)
To: Lucas Stach
Cc: Krzysztof Hałasa, Liu Ying, Maxime Ripard, Marco Felsch,
Marek Vasut, Stefan Agner, Simona Vetter, imx, Fabio Estevam,
Pengutronix Kernel Team, Maarten Lankhorst, Sascha Hauer,
Frank Li, linux-kernel, dri-devel, Thomas Zimmermann,
David Airlie, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 5322 bytes --]
Hi Lucas,
On Mon 30 Mar 26, 18:44, Lucas Stach wrote:
> Am Montag, dem 30.03.2026 um 18:09 +0200 schrieb Paul Kocialkowski:
> > After weeks of investigation I finally narrowed it down to a part of the nxp
> > original code that is missing in the upstream driver:
> > https://github.com/phytec/linux-phytec-imx/blob/v6.6.23-2.0.0-phy/drivers/gpu/imx/lcdifv3/lcdifv3-common.c#L492
> >
> Thanks for tracking this down! It was also on my list of things to look
> at.
Glad that it helps :)
> > A big old sleep that waits for the DMA engine to finish handling the current
> > frame before it is disabled. When this delay is not respected, there seems to
> > be "unlucky" times when disabling the DMA engine too early will confuse the
> > unit and make it unable to resume proper operation later.
> >
> I think we can be a bit more clever than a indiscriminate sleep. If we
> set the shadow load enable bit in the disable sequence, we should be
> able to wait for this bit to be cleared by the hardware. All the DMA
> parameters (presumably including the enable state) should be applied by
> the hardware when this bit is cleared.
I just tried it out and it works fine, thanks! It polls for a variable delay
from < 1 ms to < 16 ms, which makes perfect sense for a 60 Hz mode.
This is much better than the hardcoded 25 ms. I'll add your Co-developed-by tag
to the final commit.
> I guess the read_poll_timeout in lcdif_disable_controller() was
> supposed to do exactly that wait, but as it was actually copied from
> the mxsfb driver, it's not working as intended. It's my understanding
> that the old lcdif HW only cleared the enable bit once it is actually
> done, but on the lcdifv3 on i.MX8MP those states are double buffered,
> so the bit in the register would be cleared instantaneously, rendering
> the wait in the current code a no-op. The only reliable indicator to
> see if the HW has updated it's internal state is to set the shadow load
> enable bit and wait for it to be cleared.
Sounds right to me. Thanks for the details! Are there resources about the
different generations/families used by nxp/freescale? They seem to be in-house
designs but with lots of different variations.
> > It is a bit surprising that the issue is not actually related to configuring
> > the display engine but to disabling it. This is why the first mode set always
> > works but subsequentil ones might fail. The crtc is essentially disabled and
> > re-enabled each time a new mode is applied.
> >
> > Adding the sleep solves the issue on my side and all mode sets now work
> > reliably. It does add a delay before returning to userspace when configuring
> > a new mode, but it seems legitimate to me if the underlying hardware is still
> > in-flight. I'm also unsure if it would apply to an async atomic commit.
> >
> This hardware doesn't support async commits. All DMA state changes are
> applied during vblank when the shadow load enable bit is set.
Ah sorry I meant non-blocking atomic commit, not async. Since this is in the
CRTC disable path, it probably makes the userspace process sleep even in the
case of a non-blocking commit (unless this happens in a kernel thread, I'm not
sure exactly). But I guess it is legitimate to block until the previous frame
is finished if it is mandatory.
All the best,
Paul
>
> Regards,
> Lucas
>
> > I will send a patch adding the delay and the undocumented fifo clear
> > bit that was discovered in this thread too.
> >
> > All the best,
> >
> > Paul
> >
> > Perhaps there is a more elegant way to handle this
> >
> >
> > > Interestingly, Weston usually starts fine in subsequent launches.
> > >
> > > How is this first (actually second - after the first VSYNC) frame
> > > different from all the others? Maybe we're programming UPDATE_SHADOW
> > > after the actual start of blanking period, but before DE, so it has no
> > > chance to reload registers, yet the DMA is somehow not ready?
> > >
> > > The manual (LCDIF display control Register (CTRL)) suggests that the DMA
> > > (with present settings) starts to fetch FB data at the end of the
> > > previous active video pixel time (DE and pixel data going inactive):
> > > fetch_start_option (bits 9-8): Indicates when to start fetching for new
> > > frame. This signals also decide the shadow load, fifo clear time
> > > 00b - fetch start as soon as FPV begins(as the end of the data_enable).
> > >
> > > This should leave a lot of time to fill the FIFO (before the next DE),
> > > shouldn't it?
> > >
> > > 297 MHz pixclk, 3840x2160, 30 Hz, H back porch 296 pixclks, Vfp 176,
> > > V back porch 72 lines, Hfp 8 lines, VSYNC 10 lines, HSYNC 88 pixclks.
> > > HTotal = 4400 pixels which makes Vactive time = 4400 * 2160/297e6 =
> > > 32 ms, with the remaining 1.3333 ms for all the V sync stuff.
> > > --
> > > Krzysztof "Chris" Hałasa
> > >
> > > Sieć Badawcza Łukasiewicz
> > > Przemysłowy Instytut Automatyki i Pomiarów PIAP
> > > Al. Jerozolimskie 202, 02-486 Warszawa
> >
>
--
Paul Kocialkowski,
Independent contractor - sys-base - https://www.sys-base.io/
Free software developer - https://www.paulk.fr/
Expert in multimedia, graphics and embedded hardware support with Linux.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-03-30 21:16 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-19 11:45 i.MX8MP: Fix HDMI LCDIF FIFO underruns Krzysztof Hałasa
2026-03-20 2:39 ` Marek Vasut
2026-03-20 8:04 ` Marco Felsch
2026-03-20 9:25 ` Maxime Ripard
2026-03-20 13:20 ` Krzysztof Hałasa
2026-03-23 8:18 ` Liu Ying
2026-03-23 12:54 ` Krzysztof Hałasa
2026-03-30 16:20 ` Paul Kocialkowski
2026-03-25 12:40 ` Krzysztof Hałasa
2026-03-30 16:09 ` Paul Kocialkowski
2026-03-30 16:44 ` Lucas Stach
2026-03-30 21:16 ` Paul Kocialkowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox