LVDS lanes not functional on imx8mp on Torizon 7.x

I’m running into a bit of a head-scratcher here and I’m hoping to get some external input as to what might be going wrong.

Preamble:
I’d previously posted here (LVDS pixel clock not respected (Torizon 7.3, Verdin imx8mp)) and have since made the requisite kernel and DTS patches as outlined in the help article.

The issue:
After the patch, the display works as expected on a Torizon 6.8.x-based build of the OS. However, I am unable to get the display working properly on Torizon 7.1.0 with the same set of changes.

Details/observations:

  • I’ve confirmed the patch is applied correctly. I’ve scoped the LVDS_CLK lines and can see that it is indeed operating at 25MHz in both cases.
  • Torizon 7.x has some notable changes to the DeviceTree handling, so while I could not use the exact same entries as on 6.x, the display timing values were copy-pasted verbatim.
  • The display “attempts” to come up and seems functional as far as the system is concerned (e.g. running an application with EGLFS works and the garbled pattern on the display changes a bit as the application draws different screens).
  • However, as noted, the display is completely garbled and non-functional. The current finding is that it appears only two of the four LVDS data lanes are transmitting any data; the other two are idle. (specifically, LVDS_D0 and LVDS_D3 show no activity - the clock, D1, and D2 have signals).
    It’s not clear to me what would cause this since as far as I can tell this is not any sort of configurable mode.
  • I do sporadically see ldb-display-controller: Failed to create device link (0x180) with 32e90000.lcd-controller in the kernel dmesg. Trying to find information on this has been somewhat fruitless and as far as I can tell, using e.g. devmem2 to inspect the LCDIF2 peripheral it seems to be configured correctly as far as video timings and display size.

Do you have any ideas why the system might be in this weird state or where I should start digging next? I’ve already tried playing with the timing values within the allowed ranges in the datasheet (ST7262 controller), but the underlying issue seems to be the missing channels.

These are the DTS changes I added for Torizon 7.x, based off the example 10" LVDS mezzanine overlay:

  • Under the / root node:
panel_lvds {
   	compatible = "panel-lvds";
   	#address-cells = <1>;
   	#size-cells = <0>;
   	backlight = <&backlight>;
   	data-mapping = "vesa-24";
   	width-mm = <108>;
   	height-mm = <64>;
   	panel-timing {
   		clock-frequency = <24000000>;
   		hactive = <800>;
   		vactive = <480>;
   		hback-porch = <40>;
   		hfront-porch = <40>;
   		vback-porch = <8>;
   		vfront-porch = <8>;
   		hsync-len = <7>;
   		vsync-len = <7> ;
   		hsync-active = <0>;
   		vsync-active = <0>; 
   		pixelclk-active = <1>;
   		de-active = <1>;
   	};
   	port {
   		panel_lvds_in: endpoint {
   			remote-endpoint = <&lvds_out>;
   		};
   	};
   };
  • elsewhere, changes to existing nodes:

&backlight {
	status = "okay";
	default-brightness-level = <0>;
	pwms = <&pwm3 0 6666667 0>;
};

&media_blk_ctrl {
       assigned-clock-rates = <500000000>, <200000000>,
                              <0>, <0>, <168000000>; // 24MHz
};

// // Enable items from the stock SoC config for graphics:
&gpu_2d {
	status = "okay";
};

&gpu_3d {
	status = "okay";
};

&lcdif2 {
	status = "okay";
};

&ldb {
	status = "okay";
	lvds-channel@0 {
		fsl,data-mapping = "spwg";
		fsl,data-width = <24>;
		status = "okay";

		port@1 {
			reg = <1>;

			lvds_out: endpoint {
				remote-endpoint = <&panel_lvds_in>;
			};
		};
	};
};

&ldb_phy {
	status = "okay";
};

&mix_gpu_ml {
	status = "okay";
};

&ml_vipsi {
	status = "okay";
};

Hi, I’m the Toradex AI Assistant.

I might make mistakes or occasionally get you wrong. Our support team will step in if needed.


LVDS Display Issues with Verdin iMX8M Plus on Torizon 7.x

Based on your description of the LVDS display working on Torizon 6.8.x but showing garbled output with only partial data lanes active on Torizon 7.x, there are several areas to investigate:

Device Tree Overlay Configuration

For Torizon 7.x, you should start with the pre-built device tree overlays that Toradex provides (1). The Verdin iMX8M Plus supports several LVDS configurations:

  • verdin-imx8mp_panel-cap-touch-10inch-lvds_overlay.dtbo - for the 10.1" capacitive touch display
  • verdin-imx8mp_dsi-to-lvds_panel-cap-touch-10inch-lvds_overlay.dtbo - for DSI to LVDS adapter configurations

Data Mapping and Width Configuration

Looking at your configuration, there’s a potential mismatch between your panel definition and the LVDS channel settings. In your panel definition, you specify:

data-mapping = "vesa-24";

But in your LVDS channel configuration, you have:

fsl,data-mapping = "spwg";
fsl,data-width = <24>;

The data mapping should be consistent. For a 24-bit VESA mapping, the LVDS channel should typically use "vesa-24" rather than "spwg" (1).

Clock Configuration Analysis

Your media_blk_ctrl clock configuration shows:

assigned-clock-rates = <500000000>, <200000000>,
                       <0>, <0>, <168000000>; // 24MHz

The comment indicates 24MHz, but the actual value is 168000000 (168MHz). This discrepancy could be causing timing issues that manifest as missing data lanes.

Device Tree Compilation and Deployment

Since you’re working with custom device tree modifications, ensure you’re following the proper compilation and deployment process for Torizon (2). The process involves:

  1. Customizing the device tree source according to your hardware requirements
  2. Compiling the device tree source using TorizonCore Builder’s dt apply command
  3. Deploying the compiled device tree to your Torizon OS image

Troubleshooting Steps

  1. Verify Overlay Application: Use the TorizonCore Builder to ensure your custom overlay is being applied correctly (3)

  2. Check Data Mapping Consistency: Align the data-mapping property in your panel definition with the fsl,data-mapping in your LVDS channel configuration

  3. Review Clock Settings: Verify that your clock configuration matches your intended pixel clock frequency

  4. Test with Reference Overlay: Try using one of the pre-built LVDS overlays as a baseline to confirm the hardware is functioning correctly (1)

The issue with only two of four LVDS data lanes being active suggests a configuration mismatch rather than a hardware problem, especially since it works correctly on Torizon 6.8.x.

Best regards, Toradex AI Assistant.


Did you like my answer? :+1: :-1:

If I answered your question, please tick the “Solution” checkbox.

For follow-up questions to me, please use @ToradexAI in your post.

Note the AI response is not correct here. The IMX driver uses “spwg” to designate 24-bit VESA per

and the clock value in the media block must be multiplied by 7 as documented in the help article.

Greetings @bw908,

As a sanity check, if you remove the patches/changes related to the pixel clock. Does this fix the issue with the data lanes? Of course the display won’t work with the incorrect pixel clock, but I’m just curious if all the data lanes would be transmitting in this case.

Another thing to check, when you say “same set of changes” do you mean exactly the same? The patches/changes for the pixel clock on 6.X vs 7.X are slightly different:

Otherwise it would be quite strange that half the data lanes are not transmitting. As you said I don’t believe this is something that can be changed/configured just via device tree changes.

Best Regards,
Jeremias

:thinking:

That’s interesting - yet yields some completely counterintuitive results that only add to the confusion:

  • I started out trying to apply these changes to a 7.x based build and so used the 7.x patch and DTS modifications.
  • I encountered the missing lane issue, so I then switched the yocto build to 6.8.1 base as a sanity check (since we’ve had “known-working” LVDS there, albeit with a different higher-frequency panel). The 7.x patch for the clock checks applies successfully to 6.x (with fuzz). I also pulled in a “known good” 6.8.1 LVDS dts configuration (with the updated timings and tweak to media_blk_ctrl).
    • This largely “just worked” on the first attempt so I did not dig any further - and so completely missed the steps talking about patching clk-pll14xx.c.

If anything I’d have expected the 6.x build to not work at all without the clock patch. But I just double checked with a scope and confirmed that it is indeed clocking the display at 25MHz even without the PLL changes.

I’ll try your suggestion to run with an unpatched kernel and a “supported” frequency on 7.1 as an additional data point - but I probably won’t get to that until Friday.

I started out trying to apply these changes to a 7.x based build and so used the 7.x patch and DTS modifications.

I see, I had the assumption that maybe you started out working on 6.X first, got that working, then moved to work on 7.X. I was thinking maybe you used the 6.X patch on 7.X as well, and somehow that could explain the issue.

But, if you did start out with 7.X and used the appropriate code changes then that does add some confusion here.

I’ll try your suggestion to run with an unpatched kernel and a “supported” frequency on 7.1 as an additional data point - but I probably won’t get to that until Friday.

Please do let us know once you’ve tested this. It would be a good baseline just to make sure the patch didn’t somehow introduce this issue.

Last I checked I do believe the kernel with no changes does run the LVDS display we sell as expected. Though I will check if maybe the documented pixel clock changes for 7.X are somehow wrong or outdated.

Best Regards,
Jeremias

One more thing. I took another look at your device tree changes. I noticed you’re driving the backlight node via pwm3 unlike the mezzanine overlay which uses the backlight_mezzanine node (pwm2) instead. Though I will assume this difference is intentional.

However, in your changes i don’t see the pwm3 node being enabled. Is this node enabled somewhere? Or maybe you just forgot to paste the change to that node when you shared your changes.

I believe this node is disabled by default. Or at least in our overlays we always explicitly enable the respective pwm* nodes for whatever backlight node will be used.

Finally, I noticed you set the default-brightness property for backlight to be 0. Is that intential as well? I understand this to mean the backlight is just off.

Best Regards,
Jeremias

Yes - sorry for the confusion. I do have all PWM channels enabled and are indeed using PWM3_DSI to drive the brightness control (and the backlight is working as expected - it turns on when the display is initialized by the OS). the default-brightness of zero is also vestigial from previous testing.

Okay, I have some more findings. It looks like the “dead” channels seems to be related to the state in which Plymouth and/or the kernel startup places the display (probably related to the known issue with busted plymouth and native LVDS in early 7.x that’s been posted about here).

I was operating on the assumption that Plymouth was functional and drawing to the screen during my previous probing that found the dead channels - since I was seeing clock activity.

Starting Weston causes all four channels to come alive. That said, it seems like the above is still a relevant piece of data given the following info - almost like there are two “halves” to the LVDS interface that are out of sync…

However:

The channels that were not working before… while they have activity… seem to still be clocked at the incorrect 74Mhz clock rate. This explains why the display is completely garbled.

Scope traces:

LVDS_CLK_P:

LVDS_D2_P:

LVDS_D3_P:

LVDS_D1_P looks similar to D2, and D0 looks similar to D3. Note the horizontal axis and scope cursors have not changed position across screenshots.

This suggests there is a deeper issue in the driver somewhere that’s not setting things up correctly. As far as the system is concerned though, I see the correct frequencies for 24MHz (and *7@168MHz) for PLL1:

It looks like the “dead” channels seems to be related to the state in which Plymouth and/or the kernel startup places the display (probably related to the known issue with busted plymouth and native LVDS in early 7.x that’s been posted about here).

Okay yes that would explain things then, at least what you were observing at system start.

So in summary with your follow-up investigations:

  • 2 data channels are at the correct patched clock speed
  • The other 2 channels are at the original ~74Mhz.
  • From Linux’s point of view the speed/frequency is “correct”.

That is odd. I agree with your assessment that this definitely seems driver level or at least something in that stack and is probably unrelated to device tree for the most part.

In 6.X the driver was capable of this as per your findings. So something changed in 7.X.

This is probably not trivial to determine though. Of course as you know NXP has stood firm in their stance on the hard-coded frequencies for their LVDS driver on this SoC. That does mean this patch workaround we have is not well-tested, and not-supported as far as NXP is concerned.

This patch was tested on a few LVDS displays just to verify. On the ones tested we did not see any major issues. Of course it’s not feasible for us to validate and guarantee the same results on every possible frequency. In fact NXP even claimed that trying to patch certain frequencies could have unexpected results. If true, I wonder if that is what is happening here.

Again though, would probably need to sift through driver differences between 6.X and 7.X to see what could have changed the behavior here. Since we know it was at least possible before.

Best Regards,
Jeremias

Thanks for the confirmation. I’d expected as much.

At this point I think this is largely now an educational exercise; we can do our initial work with a 6.8 based OS, and the next prototype of the product will use a MIPI display anyway.

An interesting observation here is the media_disp2_pix value in my clock printout is still at 84 MHz - That’s close enough to the frequency observed on the scope it’s within the visual-estimate error (because it’s not trying to measure a uniform clock but rather a data stream frequency).

The example output from another user in this thread (Limited PLL options for setting up LVDS pixel clock on IMX8MP - NXP Community) seems to indicate the pixel clock should be running at the exact frequency specified in the display timing. So likely this is the root cause of our incorrect clocking issue.

And indeed, checking against the 6.8 build shows the clock tree is configured very differently:

As to how to fix it though… I agree it’s probably an issue buried somewhere in the driver(s) from NXP.

At this point I think this is largely now an educational exercise; we can do our initial work with a 6.8 based OS, and the next prototype of the product will use a MIPI display anyway.

Okay that’s good to know at least. So it’s not blocking for you then correct?

And indeed, checking against the 6.8 build shows the clock tree is configured very differently:

Yeah that’s the problem with just trying to implement changes on top of the NXP drivers with no actual support from them. Any change they do can completely change or break behavior and they have no incentive to keep things compatible.

Do you have any further questions or issues related to this topic?

Correct, it’s not blocking for us and we have a path forward. We’ll leave it here for now since we have what we need on 6.8.1. Hopefully this thread helps someone else that stumbles across the same issue.

Thanks!

That’s good to know at least. I will mention this to our team internally too. Maybe if there’s bandwidth we can investigate what exactly is going on here with the clocks on 7.X. Though it’s hard to say if we can patch around whatever NXP has changed in their software stack here to make it work like it did in 6.X.

Best Regards,
Jeremias

Some additional casual experimentation yielded the following observations. Perhaps the original 6.x changes are based on e.g. an NXP driver bug where changing the PLL1 “value” actually only changes one of its derived clocks and unintentionally makes it “work”:

In 6.x:

  • The DTS changes suggest we are adapting the PLL clock from 1039.5MHz, but the clocktree debug suggests it has not been modified. Only the PLL ref_sel (and disp2_pix) has changed to match that of the display panel.
  • The pixel clock for LCIDF2 is an integral divisor of this value, presumably the best match the driver found for achieving the target pixel clock.

In 7.x:

  • The actual PLL1 seems to also be modified by the DTS changes. Presumably since it’s now running at a fraction of the normal rate, the driver has an issue determining the correct scaling factor to get to the target pixel clock frequency.
  • I experimented with a few tweaks and trying to e.g. set the disp2_pix clock directly in the DTS but those changes were being ignored. I did see the disp2_pix value sometimes end up at other integral factors of the 168MHz PLL1 clock, but never in a way that would satisfy the required pixel clock of ~23-7MHz needed by the display.

Thank you for the additional observations. I did confirm with my colleague that the patch for 7.X was working and tested for at least some LVDS displays. I wonder if the driver just happened to behave well for the frequencies that those test displays needed.

In any case, as I said I did report this internally for visibility.

Best Regards,
Jeremias

1 Like