Close

Debuging Screen issues

A project log for Linamp

Your favorite music player of the 90s, but in real life

rodmgRodmg 06/20/2024 at 23:130 Comments

Recently I started building a second Linamp, using some extra spare parts I had from the original build and ordered the rest of the parts I needed.

One of the most important parts is the screen, it is sold under several brand names by different sellers in Amazon and originates from China, the generic model seems to be "P79-T", which is a 7.9'' ultra wide screen with touch capabilities.

When I did the original build, I struggled to get it working correctly with the Raspberry Pi - because it uses a non-standard resolution, it requires some manual configuration in order to make it work, which is specified in the manual that comes with the screen.

The thing is, the configuration values mentioned in the manual don't really work, and now I just discovered that the correct settings seem to vary between same-model screens.

In short, the configuration needed involves modifying the "config.txt" file that lives in the Raspberry Pi boot partition, the manual instructs you to set the following values:

# DON'T USE THIS! This probably won't work
max_usb_current=1
hdmi_group=2
hdmi_mode=87
hdmi_timings=400 0 100 10 140 1280 10 20 20 2 0 0 0 60 0 43000000 3

However, when I used those values on my original screen, I got a flickering image with glitches and lines:

After a lot of trial and error, I was able to fix it by using the following values:

# config.txt changes that worked for my original screen
hdmi_cvt=400 1280 60 3
hdmi_group=2
hdmi_mode=87
hdmi_drive=2
dtoverlay=vc4-kms-v3d

 I also updated the cmdline.txt file, which controls the startup of the Linux Kernel, adding the following parameters:

video=HDMI-A-1:400x1280M@60,rotate=270

This worked! I now got a clean picture and everything seemed to work great!

However this was not the whole story...

Now that I'm building a second device, I used another sceen, which came from the same Amazon vendor, in the same box, same manual and same outside looks, but when I connected it to the Raspberry Pi with the same SD card as before, I got a different set of glitches:

These screens come with a metal shell which I remove in order to fit it inside my custom case, when I opened it, I saw a slight difference:

My original screen back side:

The new screen back side:

As you can see, the electronics seem the same, but the actual display panel is different.

And now I also know that the hdmi timing configurations for these are also different.

Understanding the issue

There are several things at play here. First of all, these screens, when connected to a macOS or Windows PC, work just fine, but when connected to a Linux machine, being it a Raspberry Pi or PC, they have the issues I'm seeing.

This seems to be due to non-standard HDMI protocol implementations in these screens, which macOS and Windows seem to correctly parse (probably because when these screens were designed, they were tested to work on those OSes primarily), but Linux is having issues with it.

Specifically the issues seem related to the "EDID" a kind of identification that displays send to the host computer when connected, which tell the computer what video modes the display supports so it can auto-configure it.

So that's why the manual instructs us to use the "hdmi_timings" in the Raspberry Pi - that setting overrides the auto configuration of the display and forces specific signal timings that the display needs to work.

Those timings seem to depend on the actual display panel, so they seem to vary. In an ideal world, the controler board on the display would be correctly configured to report the actual good values the panel supports to the OS, so the OS could auto configure it. But the world is not ideal.

Also, now comes another complication: How did I manage to make it work without using hdmi_timings on my original display? Well, it turns out that I didn't get it 100% right there, if you look closely, when the Raspberry Pi boots, it firsts displays a test color pattern, and then starts showing some text while the Linux Kernel boots, then, the screen flickers, and you get more Linux kernel text, then it flickers again and you get your graphical interface.

So, if you look at those details when Linamp boots, you will see that we still get the glitches on the first screens, and those only get fixed once we get into the Linux kernel and the graphical interface. (I disabled the actual test pattern and kernel output so you cannot see it easily).

I'm using DietPi Bookworm, which is a recent release with a recent Raspberry Pi Linux kernel, this means that we are now using the new open-source KMS graphic driver. Previously, the Raspberry Pi used a propietary graphics driver which delegated a lot of the display interfacing to the VideoCore GPU, including the screen timing configurations. Now, the KMS driver does this, so we have two different codebases interfacing with our screen: During the initial test pattern and kernel loading screens, we are on the boot loader which is still using the VideoCore GPU directly to configure the screen, here is where the hdmi_timings and any other setting in the config.txt file is being used. However, due to the dtoverlay=vc4-kms-v3d setting I used, when we get into the Kernel, we start using the KMS graphic driver, which seems to correctly detect my original screen and configures it correctly. However this is not the case with the second screen.

Figuring out the timings for the second screen

First I did some more trial and error, with no success, and then I did some reading.

These resources got me to the right path:

- Using Weird Displays with Raspberry Pi: https://learn.adafruit.com/using-weird-displays-with-raspberry-pi/everything-else

- Raspberry Pi config.txt docs: https://github.com/tback/raspberrypi_documentation/blob/master/configuration/config-txt/video.md
- Troubleshooting KMS HDMI output: https://pip.raspberrypi.com/categories/685-whitepapers-app-notes/documents/RP-004341-WP/Troubleshooting-KMS-HDMI-output.pdf

The last one was specially clarifying, it explains the change from using the propietary graphics driver to the KMS driver and the differencies and issues that could arise, also the Adafruit post helped me on how to derive the timing values, altough some of the steps there don't apply anymore due to recent changes in software.

The solution so far has been to not use KMS and force using the propietary driver, and also derive a specific set of timing values for the device.

These are the steps I followed to derive the hdmi_timings:

  1.  In config.txt, enable KMS by setting `dtoverlay=vc4-kms-v3d` and reboot
  2. SSH into the pi and, with the screen connected, do `edid-decode /sys/class/drm/card1-HDMI-A-1/edid`, you will get something like this:
  3. Detailed Timing Descriptors:  
       DTD 1:   400x1280   59.995729 Hz   5:16    82.194 kHz     61.810000 MHz (side by side interleaved, 296 mm x 1280 mm)  
                    Hfront  160 Hsync  32 Hback  160 Hpol P  
                    Vfront   30 Vsync  30 Vback   30 Vpol N
  4. Follow https://learn.adafruit.com/using-weird-displays-with-raspberry-pi/everything-else#hdmi-timings-if-necessary-3080203 to derive the values, start with this: `hdmi_timings=400 0 100 10 140 1280 10 20 20 2 0 0 0 60 0 43000000 3` and update all the values except aspect_ratio and the ones that are not specified in the guide.
  5.  Update config.txt with the new hdmi_timings and comment out `#dtoverlay=vc4-kms-v3d`. Reboot.

After all this, my changes to config.txt looked like this (showing only relevant lines):

hdmi_group=2  
hdmi_mode=87  
hdmi_timings=400 0 160 32 160 1280 10 30 30 30 0 0 0 60 0 61810000 3  
hdmi_drive=1  
hdmi_force_mode=1
display_hdmi_rotate=1
#dtoverlay=vc4-kms-v3d

And now, the new display works perfectly! Even the initial bootloader screens look perfect.

However, If I connect the original screen, it again has glitches, I'll probably need to derive a different set of hdmi_timings for that one.

Update: Here are the correct timings for my original screen, derived following the previous process:

hdmi_group=2  
hdmi_mode=87  
hdmi_timings=400 0 50 30 50 1280 10 30 20 30 0 0 0 60 0 43240000 3  
hdmi_drive=1  
hdmi_force_mode=1
display_hdmi_rotate=1
#dtoverlay=vc4-kms-v3d 

The Dilema

Now the dilema: I wanted to distribute updates to Linamp as OS images, however with this new finding, so far I cannot guarantee that my updates will work with all screens.

I've ordered a third screen to see if I get the same issue again or if I can see any kind of pattern, to get a better solution. Otherwise we will need to keep our hdmi_timings for each device and remember to update those if we reflash the SD card.

Discussions