Hi all,
I'm working on bringing up a command-mode MIPI DSI panel (CH13726A)
on an i.MX8MP using the samsung-dsim bridge, and I'm seeing what
appears to be a timing-dependent issue during the enable sequence.
I'm hoping someone familiar with the DSIM hardware can clarify
whether my understanding is correct.
Using the upstream driver without any changes causes my panel to come
up only once every 5-6 boots. While I know command mode does not yet
support TE IRQ synchronization for my setup, I expected the panel to
at least come
up every boot even without VSYNC synchronization.
Immediately before samsung_dsim_set_display_enable(), a working boot
shows:
STATUS = 0x8010010f
FIFOCTRL = 0x0155551f
while a failing boot consistently shows:
STATUS = 0x8010040f
FIFOCTRL = 0x0155541f
>From the register definitions, my understanding is that the working
case indicates the clock lane is in STOP state (LP11) before
enabling video output, while the failing case indicates the controller
has already left STOP state and the HS clock is already active. The
FIFO contents also differ between the two cases.
To experiment with this, I added a loop that waits until the
controller reports
(status & 0xf) == 0xf &&
(status & DSIM_STOP_STATE_CLK)
before proceeding with the remainder of
samsung_dsim_set_display_enable(). Waiting for this condition
significantly improves the success rate of panel initialization.
Noticing that samsung_dsim_set_display_enable() sets the
DSIM_MAIN_STAND_BY bit, I also tried toggling that bit. Surprisingly,
doing so causes the panel to initialize almost every time, although it
often initially displays a white, purple or green screen before
eventually rendering the framebuffer correctly.
The following hack, combined with the polling loop above, increases
the panel bring-up success rate and makes it work almost always:
reg |= DSIM_MAIN_STAND_BY;
samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
msleep(20);
reg &= ~DSIM_MAIN_STAND_BY;
samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
msleep(20);
reg |= DSIM_MAIN_STAND_BY;
samsung_dsim_write(dsi, DSIM_MDRESOL_REG, reg);
msleep(20);
timeout = 10000;
do {
reg = samsung_dsim_read(dsi, DSIM_STATUS_REG);
if ((reg & 0xf) == 0xf &&
(reg & DSIM_STOP_STATE_CLK))
break;
usleep_range(1000, 1500);
} while (--timeout);
This is obviously just an experiment and not something I'd propose
upstream. I was only trying to understand the hardware behavior.
What surprised me is that toggling DSIM_MAIN_STAND_BY appears to make
the panel initialize much more reliably than simply setting the bit
once. This made me wonder whether toggling DSIM_MAIN_STAND_BY causes
the DSIM to restart or resynchronize some internal state machine, or
perhaps flush or reinitialize some internals, rather than merely
enabling video output as I originally assumed.
My main question is: what hardware event is expected before
samsung_dsim_set_display_enable() is called so that the display
can start up normally every time?
Is there already an expected synchronization point in the enable
sequence that I should be waiting for instead of polling
DSIM_STATUS_REG, or does this behavior suggest that I'm
misunderstanding the intended initialization sequence?
Thanks for your time and consideration.
Best regards,
Advait