Jitter when using DSI-> LVDS Adapter

Hello,
(On Torizon OS 6.8.0)

I am using a slightly modified version of the DSI to LVDS adapter, basically all that’s been changed is the removal of the backlight and touchscreen related functionality and adding a JAE connector to attach to twisted pairs to our display. I have configured the DTS for the timing of the new LVDS display, but it has visual glitching where the left half of the display seems to be jittering around left/right a few pixels on a line by line basis. The first line seems to jitter more, up to half the screen of pixels. In the below screenshot, the top line seems to have shifted ~4 pixels.

My display has these timings in the DTS:

  panel-timing {
    clock-frequency = <24400000 25200000 27300000>; // Min/typ/max clk in hz
    de-active = <1>;                                // active high display enable in datasheet
    hactive = <640 640 640>;                        // horizontal resolution
    hback-porch = <50 53 70>;                       // Min/typ/max #clock
    hfront-porch = <50 53 70>;                      // Min/typ/max #clock
    hsync-len = <50 53 70>;                         // Min/typ/max #clock
    pixelclk-active = <1>;                          // positive edge
    vactive = <480 480 480>;                        // vertical resolution
    vback-porch = <12 15 18>;                       // Min/typ/max #clock
    vfront-porch = <12 15 18>;                      // Min/typ/max #clock
    vsync-len = <12 15 18>;                         // Min/typ/max #clock
  };

It is a 18 bit display.

The display does not use HS and VS LVDS signals, and relies on the DE signal. It does not provide separate front porch / back porch / sync length values and only gives the totals. When I distribute these times equally amongst the timings in the DTS overlay, the issue occurs. I have tried specifying individual values rather than max/min/typ, I’ve tried messing with polarity of clock/de, and I’ve also tried using values from the RGB parallel version of this display which specifies the actual pulse width / front/back porch numbers. All of these either don’t work at all or have the jitter seen above.

From the datasheet:

  • CLK Frequency (min/typ./max): 24.4/25.2/27.3 MHz
  • Horizontal
    • Display Data: 640 Clks
    • Total Cycle Time (min/typ./max): 688/800/850 Clks
  • Vertical:
    • Display Data: 480 H
    • Total Cycle Time (min/typ./max): 516/525/535 H

Could there be an issue with the DTSses such that the pixel buffers aren’t being filled fast enough? Or could there be an issue with jitter due to spread spectrum? I’d very much appreciate any assistance here diagnosing the issues.

I have also played with i2cset/i2cget to use values from the DSI tuner from TI, but the differences in values don’t seem to change the issue.

However, putting the DSI to LVDS bridge in the test pattern mode shows a proper test pattern with no jitter - so it is likely that the LVDS portion (cables, display, configuration) works but the DSI portion to the bridge and the corresponding DTS/DSI configuration is broken.

Hi, I’m the Toradex AI Assistant. The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello,

The jittering issue you’re experiencing with your display connected via the DSI to LVDS adapter could stem from several factors, including incorrect timing settings in the device tree source (DTS) or signal integrity issues.

Potential Causes and Solutions:

  1. DTS Configuration:

    • Ensure that the timing parameters in your DTS file accurately reflect the specifications provided in your display’s datasheet. This includes the clock frequency, horizontal and vertical active areas, and total cycle times.
    • Since your display relies on the DE signal and not HS/VS, make sure the de-active setting is correctly configured.
    • Double-check the distribution of front porch, back porch, and sync length values to ensure they align with the total cycle times specified by the display manufacturer.
  2. Signal Integrity:

    • Verify that all connections, especially those involving the JAE connector and twisted pairs, are secure and free from interference.
    • Consider the quality of the cables used and ensure they are suitable for high-frequency signals.
  3. Spread Spectrum Clocking:

    • If spread spectrum clocking is enabled, it might introduce jitter. You can try disabling it to see if the issue resolves.
    • Refer to your system’s documentation on how to adjust or disable spread spectrum settings, particularly if using a Verdin iMX8M Plus module.
  4. Testing and Debugging:

    • Experiment with different timing configurations to see if the jittering changes or resolves.
    • Use an oscilloscope to check the signal integrity and timing of the LVDS signals.

By carefully reviewing and adjusting these aspects, you should be able to identify and resolve the jittering issue. If problems persist, consider testing with a different display or adapter to further isolate the cause.

Best regards,
Toradex AI Assistant.

Please, also check if these links can help you solve your problem:

https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/Adapting-evkmimxrt1170-lvgl-demo-widgets-example-to-SN65DSI83/td-p/1587238.

Looks like a signal integrity issue. Do you observe the same effects when using the original Toradex DSI-to-LVDS adapter with your display?

  • Setting the bridge to display a test pattern results in no jitter - so the LVDS side of signal integrity is ruled out - I believe.
  • The DSI side of the adapter is exactly the same routing, the PCB parameters should be the same.
  • We are using this version of the board as it has the correct connector and drive circuitry for our display.

It seems like you are ruling out a potential hardware issue with the setup you are using. If that is the case, we can focus on identifying a software-related problem. Please double-check the correctness of your device tree (DT) modifications.

I have detailed the modifications above - I am asking for assistance with the troubleshooting here. I have seen there are commits added in the BSPs to ensure that the buffers fill correctly, and Toradex has information about how to patch Linux to support setting specific clocks on the video PLL for raw LVDS - so, information along those lines. I’m looking for pointers here, whether or not this could be an issue with Torizon OS 6.8.0, whether or not I should be messing with the DSI side of the equation. The DSI configuration in the device tree seems rather minimal - it seems that the bridge driver should attempt to do what the TI tuning tool does, and I’m wondering if it could be configuring it wrong or there’s another aspect of the clock tree or patches to the kernel I should be investigating.

If by “raw LVDS” you are referring to the native LVDS interface of the i.MX8M Plus, please note that it is not applicable in this case since you are using the i.MX8M Plus DSI interface instead. We have tested the Toradex LVDS display (connected through Toradex DSI-LVDS mezzanine board) with Torizon OS 6.8.0 and did not observe any jitter. Based on this, I still suspect that the issue could be related to signal integrity on the DSI link. Although you provided a snippet of your device tree, it would be better to share the full overlay source code.

I am referring to the LVDS after the bridge - I tell the bridge to display a test pattern, and this test pattern does not have the jitter - so the thought is that the LVDS signal integrity is fine. So, the remaining part of the equation is simply the bridge, the software, and the DSI connection. The software should be the only variable here.

The thought is that perhaps the rates used here are causing an issue with timing/underfill of buffers in the DSI side. So, the displays that Torizon tested worked, but when I try to run at 25Mhz it does not.

Here’s the full overlay set:

verdin-imx8mp_dsi-to-lvds_panel-*-lvds_overlay.dts

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
 * Copyright 2020-2022 Toradex
 */

// Verdin DSI to LVDS Adapter orderable at Toradex.

/dts-v1/;
/plugin/;

/ {
	compatible = "toradex,verdin-imx8mp";
};

#include "verdin-imx8_mipi-dsi-to-sn65dsi84.dtsi"
#include "display-tx14d204vm0baa_sn65dsi84_overlay.dtsi"
#include <dt-bindings/pwm/pwm.h>

&atmel_mxt_ts {
	status = "okay";
};

&backlight {
	pwms = <&pwm3 0 6666667 PWM_POLARITY_INVERTED>;
	status = "okay";
};

&gpu_2d {
	status = "okay";
};

&gpu_3d {
	status = "okay";
};

/* LCDIF to MIPI-DSI */
&lcdif1 {
	status = "okay";
};

&mix_gpu_ml {
	status = "okay";
};

&ml_vipsi {
	status = "okay";
};

&vpu_g1 {
	status = "okay";
};

&vpu_g2 {
	status = "okay";
};

&vpu_vc8000e {
	status = "okay";
};

&vpu_v4l2 {
	status = "okay";
};

&reg_dsi_lvds {
	/* Verdin CTRL_SLEEP_MOCI# (SODIMM 256) */
	gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
};

display-tx14d204vm0baa_sn65dsi84_overlay.dtsi

&lvds_ti_sn65dsi84 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@2 {
			reg = <2>;

			lvds_out_panel: endpoint {
				remote-endpoint = <&panel_in_lvds>;
			};
		};
	};
};

&panel_lvds {
	compatible = "panel-lvds";
	backlight = <&backlight>;
	data-mapping = "jeida-18";
	height-mm = <86>;
	width-mm = <115>;
	status = "okay";

	panel-timing {
		clock-frequency = <25000000>; // Min/typ/max clk in hz
		de-active = <1>;                                // active high display enable in datasheet
		hactive = <640>;                        // horizontal resolution
		hback-porch = <140>;                       // Min/typ/max #clock
		hfront-porch = <10>;                      // Min/typ/max #clock
		hsync-len = <60>;                         // Min/typ/max #clock
		pixelclk-active = <1>;                          // positive edge
		vactive = <480>;                        // vertical resolution
		vback-porch = <40>;                             // Min/typ/max #clock
		vfront-porch = <5>;                            // Min/typ/max #clock
		vsync-len = <5>;                         // Min/typ/max #clock
	};

	port {
		panel_in_lvds: endpoint {
			remote-endpoint = <&lvds_out_panel>;
		};
	};
};

The particular timings and settings here have been modified a bunch of times to no avail using various splits between front/back/sync timings. This display only uses DE and I’ve been told the rest of the timings do not matter, but I’ve tested it nonetheless.

Initially you provided:
panel-timing {
clock-frequency = <24400000 25200000 27300000>; // Min/typ/max clk in hz

Later:
panel-timing {
clock-frequency = <25000000>; // Min/typ/max clk in hz

Which one are you actually applying? Otherwise, your Device Tree Overlays look OK, which leads me to conclude it might be a hardware issue. I’d recommend ordering or making a custom cable to connect your display to the Toradex DSI-to-LVDS adapter to either exclude or confirm a hardware issue.

I’ve tried several clock frequencies. I am aware the bridge does not operate at 24Mhz. The rest of the timings there are attempts to remove the jitter. I’ve attempted pretty much the whole range of ratios between the front/back porch and sync intervals.

I have ordered the official DSI->LVDS adapter and I am making a cable to fit on the IMX8MP Mezzanine board LVDS header (or the DSI->LVDS adapter when it comes in).

My best guess as to what is happening is an issue with the DSI layers, something akin to this snippet from drivers/gpu/drm/bridge/sec-dsim.c:1619

	/* workaround for CEA standard mode "1280x720@60" "1920x1080p24"
	 * display on 4 data lanes with Non-burst with sync
	 * pulse DSI mode, since use the standard horizontal
	 * timings cannot display correctly. And this code
	 * cannot be put into the dsim Bridge's mode_fixup,
	 * since the DSI device lane number change always
	 * happens after that.
	 */
	if (!strcmp(adjusted_mode->name, "1280x720") &&
	    drm_mode_vrefresh(adjusted_mode) == 60   &&
	    dsim->lanes == 4		    &&
	    dsim->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
		adjusted_mode->hsync_start += 2;
		adjusted_mode->hsync_end   += 2;
		adjusted_mode->htotal      += 2;
	}

I am using 640x480, perhaps there’s an issue similar to this that requires non-burst mode, but the bridge driver only supports burst mode at the moment? Shot in the dark.

Adjusting the front porch, back porch, and other timing parameters of the panel only affects the LVDS side, which you mentioned is working correctly. Unfortunately, we are unable to reproduce your issue locally, which makes debugging challenging. Could you measure the DSI clock rate after applying your overlays? I’m very curious to see the results when using the Toradex DSI-to-LVDS adapter.

With our adapter, measuring the clock rate with a standard 10x oscilloscope probe (which loads the line a little) is 75Mhz, which makes sense if it chooses a divisor of 3. We’ve also diffed the registers set by the driver against the TI tuning tool, and we’ve played with the delay values there to match the tuner to no avail.

The test with the LVDS->DSI will have to wait for shipping, but I may have a way to get access earlier.

Why did you set the PLL to disabled (reg 0x0D)? Does the jitter occur immediately after boot, or only when using the TI tool? I’d also suggest experimenting with the equalization settings for the DSI Channel A Clock (reg 0x11).

The root of the problem seems to be BURST mode with the bridge, and that the IMX8MP has a fixed root video clock that feeds all the video interfaces, and those video interfaces can only divide up that root clock in a number of ways. LVDS for example - can only divide it by 7 (Display Output, Resolution and Timings (Linux) | Toradex Developer Center). I’m not exactly sure what the limitations are for the pixel clock for DSI, but - when I set up a pixel clock for the panel in the DTS of 25Mhz, the DSI pixel clock seems to actually be slightly under, in other cases it may be slightly over. This mismatch seems to cause issues feeding the bridge fast enough which is trying to drive another display at a fixed timing.

imx8mp.dtsi has a fixed clock for the root clock:

clk-pll14xx.c has a fixed table for configurations for the PLL:

So, I can only assume that what was happening is that the fixed 1039.5MHz couldn’t be divided down accurately enough to make a pixel clock that feeds the 25MHz requirement sufficiently with the clock ranges/timings the bridge driver configures.

But, since commit b09c68dc57c9 (“clk: imx: pll14xx: Support dynamic rates”) - this video PLL can basically arbitrarily be set, and it calculates these constants for you. So, I searched around to find someone who used this and found:

https://lore.kernel.org/linux-arm-kernel/6bc5b8d7-ff10-4860-ac46-1460a7d850da@denx.de/T/

This sets up CLK_SET_PARENT on the imx8mp pixel clocks so that they can reconfigure the video PLL to be ideal.

Now, this commit was later reverted: [v7,2/7] Revert "clk: imx: clk-imx8mp: Allow media_disp pixel clock reconfigure parent rate" - Patchwork

Because both of the two pixel clocks will fight to reconfigure the root video PLL. For a single display use-case, I’m pretty sure this works very well though and I’d recommend folks give it a try if they’re seeing the clock (media_dispN_pix) not divide out well. I’m pretty sure there’s a way to math out what the root video PLL should be to better divide down, but I’ll stick with this for my single display use-case as it will probably result in many DTSses for various pixel clock frequencies working well without needing any kernel changes.

Also, I don’t exactly understand this, but it seems that BURST mode for DSI that the bridge driver sets up causes issues. I’ve seen a few folks make this patch to the sn65dsi83.c driver. Without using sync pulse mode, I see the display do this odd interlacing pattern:

Anyway, I can now see that the pixel clock is exactly the 25MHz I set in the DTS:

This along with the BURST change results in a stable display.

Here are the changes I made:

  1. Followed Build Torizon OS from Source With Yocto Project/OpenEmbedded | Toradex Developer Center to get a Yocto build set up.
  2. Added a layer:
  3. Added these patches (note: these only apply on the torizon os 7.1.0 kernel):
    0001-Use-sync-pulse-mode-for-bridge-driver.patch (869 Bytes)
    0001-Add-CLK_SET_PARENT-to-IMX8MP-pixel-clocks.patch (4.0 KB)
  4. Added a bbappend recipe (you may want to limit this to the specific kernel version instead of using %)
    FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
    SRC_URI += "file://0001-Add-CLK_SET_PARENT-to-IMX8MP-pixel-clocks.patch"
    SRC_URI += "file://0001-Use-sync-pulse-mode-for-bridge-driver.patch"```