X.Org, MIPI, Raspberry Pi configurations and modelines

PUBLISHED ON JAN 5, 2023 / 7 MIN READ

Spoiler for the impatient

If you just want the X.Org Modeline configuration for a DXQ608-X04, it’s xrandr --newmode "your_mode_name_here" 115.57 540 610 620 666 2560 2610 2612 2630 -hsync +vsync. You then follow through the rigmarole for attaching this to your HDMI interface and setting it as the output modeline, an example for a normal 1080p display is provided below. This wasn’t tested with a DXQ608-X03 but it should work the same way. Some observations on the DXQ608-X04 are also noted below, for anyone interested.

Background

Recently, I had the pleasure of working with a monochrome LCD (specifically, a DXQ608-X04 2K monochrome display, one which is typically used with medium-range resin 3D printers). This aliexpress special came from a company called Wisecoco, under the recommendation of members of the turbo-resin discord for its application (which will be revealed soon). This weird display, among others such as circular displays, automotive displays and more, are typically driven using Mobile Industry Processor Interface, Display Serial Interface (MIPI DSI), which is a closed-source protocol with the spec only available to companies. An easily-accessible1 example of a MIPI DSI serial bus is found on the Raspberry Pi’s display ribbon output.

Fortunately for the rest of us, the kind folks at Wisecoco made a driver PCB which converts a HDMI port into a 40 pin MIPI output (which can then be converted to whatever your display needs with an adaptor board). This is where I hit my snag, as despite offering many exotic driver-display pairs, it seems the manufacturer does not make any HDMI timings available! The only glimmer of hope I had was finding a single post from an anonymous user who posted a Raspberry Pi configuration, which would be excellent if any of the single board computer were available. This post will first discuss what is normally done with configuring an X.Org display so we are familiar with the procedure and terminology, and then talk about converting Raspberry Pi config.txt hdmi_timings into X.Org modelines and vice versa.

X.Org Modelines

On Linux, (if you’re using X.org, the commands differ slightly under Wayland) there is a way to modify your display output resolution with the xrandr command. There is also a way to create a configuration (a modeline) for use with xrandr very quickly, with the cvt command. A modeline, for those not in the know, is a configuration that provides display information to the X display server about a connected monitor. These modelines, display-specific orientations, and more can then be graphically managed with arandr.

A typical process of adding an off the shelf 1080p monitor might work as follows:

First, generate a modeline configuration with cvt, which has the syntax cvt x_width y_width framerate. For this case we will do cvt 1920 1080 60 for which we are graced the output:

# 1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.16 kHz; pclk: 173.00 MHz Modeline "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync

We take the modeline section of this output and use that with xrandr to tell the X server what configuration we want to use with our new display.

xrandr --newmode "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync

The name of our HDMI interface can be checked with the xrandr command, which by itself will list all hte interfaces you have available and if they are connected. In my case my interface was called “HDMI-1”.

We then attach this mode with our HDMI output as follows:

xrandr --addmode HDMI-1 1920x1080_60.00

Finally we can try it out, and tell the X server to switch its active configuration over to the one we just created.

xrandr --output HDMI-1 1920x1080_60.00

And all should be well with the world. If it isn’t all peace and drum-circles (your display is upside-down for instance), we can modify our display’s orientation with the graphical interface arandr.

Conversion of modelines to Raspberry Pi hdmi_timings

The syntax of the Raspberry Pi’s config.txt hdmi_timings is as follows:

hdmi_timings=<h_active_pixels> <h_sync_polarity <h_front_porch> <h_sync_pulse> <h_back_porch> <v_active_lines> <v_sync_polarity> <v_front_porch> <v_sync_pulse> <v_back_porch> <v_sync_offset_a> <v_sync_offset_b> <pixel_rep> <frame_rate> <interlaced> <pixel_freq> <aspect_ratio>

And the syntax of a modeline is as follows:

pclk hdisp hsyncstart hsyncend htotal vdisp vsyncstart vsyncend vtotal [flags] Flags (optional): +HSync, -HSync, +VSync, -VSync, Interlace, DoubleScan, CSync, +CSync, -CSync

These obscure names probably don’t mean much to you unless you are familiar with how drawing on monitors work. The timings and nomenclature have their origins in when we used cathode ray tube displays, a fun way to learn more is to watch Ben Eater’s video on VGA where he makes a video card.

Nonetheless, each of these configurations can be changed to the other using these conversions:

<[h|v]_active_pixels> = [h|v]display
<[h|v]_front_porch>   = [h|v]sync_start - [h|v]display
<[h|v]_sync_pulse>    = [h|v]sync_end - [h|v]sync_start
<[h|v]_back_porch>    = [h|v]total - [h|v]sync_end

Finally, pclk, which is a decimal, can be converted to <pixel_freq>

<pixel_freq> = pclk * 1E6

Obviously, this can be used to convert from Raspberry Pi hdmi_timings back into a modeline, which is what I did for my display.

Making the DXQ608-X04 work

The only resource I had at my disposal was a single review post on Aliexpress, the text read as follows:

THIS IS NOT SUITABLE FOR LIVE-VIDEO only still images or preprocessed videos!

The resolution used is 540×2560 (it uses R G and B data to create a 1620×2560 image so you have to preprocess them meaning no live-videos!!!)

I'm using a DXQ608-X04 1620×2560 Monochrome LCD.

When you want to use a raspberry pi (I'm using a raspberry pi zero w) their provided configuration doesn't work!

Here is my own configuration that works:

#MONOCHROME 540×2560 (1620×2560) LCD CONFIGURATION!

#LCD CONFIGURATION START

hdmi_ignore_edid=0xa5000080
hdmi_group=2
hdmi_cvt=540 2560 0
hdmi_mode=87

hdmi_pixel_freq_limit=400000000
hdmi_timings=540 0 70 10 56 2560 0 50 2 20 00 0 0 0
115570000 0
hdmi_drive=2
hdmi_force_hotplug=1
disable_overscan=1

max_framebuffer_width=2560
max_framebuffer_height=2560
framebuffer_width=540
framebuffer_height=2560
framebuffer_depth=24
framebuffer_ignore_alpha=1
config_hdmi_boost=4
display_rotate=0
gpu_mem=64
dtparam=audio=off

#LCD CONFIGURATION END

Hope this helps:)

Shippi

Well Shippi, with my new-found knowledge on how to convert between RPi config and modelines, I think this just might just work.

By using the hdmi_timings part of the configuration, I ended up with the following Modeline: "DXQ608" 115.57 540 610 620 666 2560 2610 2612 2630 -hsync +vsync

Again, check the name of your interface with xrandr (in this case it was HDMI-1).

Which when added as an output mode, and switched to:

xrandr --newmode "DXQ608" 115.57 540 610 620 666 2560 2610 2612 2630 -hsync +vsync

xrandr --addmode HDMI-1 DXQ608

xrandr --output HDMI-1 --mode DXQ608

The display fired right up, and worked perfectly. This might have to be done on every boot - but that’s just a case of adding it to your .profile. [Update 22/01/2023: after a few reboots, the display is detected and the working configuration (using the method documented here) is applied to it normally. I didn’t have to put anything in my .profile, but your results may vary.]

Quirks of the DXQ608-X04

Despite claims of the contrary online - it works excellently for video. I was able to push about 24 frames per second to the display (maybe more even - I need to check).

The display resolution you have to use for the DXQ608-X04 is a bit fishy, due to the fact it’s a monochrome display. Normally, each pixel is made of a red, green and blue component, but for this monochrome display these RGB components are used as individual pixels. The order appears to be as follows2 (r)(g)(b)(r)(g)(b). Consequently, if you just push a normal output to the display, it’s squashed with a ratio of 3:1, and to get single-pixel accuracy for drawing monochrome features, you have to change the colour of the pixel you are working with.

There might be an interesting way to preprocess frames of video for this - but that will have to come later.

Conclusion

This project was about a 4/10 on my pain scale, mostly driven by the lack of documentation and the fact I fell into a lot of dead-ends along the way. Hopefully this blog post is read by someone in the future with the same problem that I had. Nonetheless, I enjoyed learning about how the X server is configured to work with displays, and the “intricacies” of HDMI timings.

Finally I’d like to pass my gratitude for the Shippi’s contribution on aliexpress for the Raspberry Pi configuration (I scoured the web for days and found nothing else).

Future thoughts

I might make a Raspberry Pi hdmi_timings to modeline (and vice-versa) calculator. If this gets added I will add this to this post.


  1. This is under the strong assumption that you can even get a Raspberry Pi, as the shortages are outrageous. ↩︎

  2. I will update this post if I have evidence of a different ordering. ↩︎