megi's PinePhone Development Log RSS

Genocide is bad

2021–11–19: Pinephone Pro LCD panel

According to /sys/class/power_supply/rk818-usb/input_current_limit the panel uses the following mode:

mode: "720x1440": 53 66000 720 760 800 840 1440 1458 1468 1485 0x48 0xa

This is problematic, becase 53 Hz is not exactly the expected refresh rate. Kernel calculates this refresh rate from other timings on the line. It is not possible to just raise the pixel clock from 66 Mhz to 74.7 MHz to compensate. If we do, the panel will have corrupted output.

The following is a initialization sequence for the panel's HX8394-F controller. It's copied here from the driver written by ayufan, and was probably copied from Android kernel, originally:

dsi_dcs_write_seq(dsi, 0xb9, 0xff, 0x83, 0x94);
dsi_dcs_write_seq(dsi, 0xb1, 0x48, 0x11, 0x71, 0x09, 0x32, 0x24, 0x71, 0x31, 0x55, 0x30);
dsi_dcs_write_seq(dsi, 0xba, 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0);
dsi_dcs_write_seq(dsi, 0xb2, 0x00, 0x80, 0x78, 0x0c, 0x07);
dsi_dcs_write_seq(dsi, 0xb4, 0x12, 0x63, 0x12, 0x63, 0x12, 0x63, 0x01, 0x0c, 0x7c, 0x55, 0x00, 0x3f, 0x12, 0x6b, 0x12, 0x6b, 0x12, 0x6b, 0x01, 0x0c, 0x7c);
dsi_dcs_write_seq(dsi, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1c, 0x00, 0x00, 0x32, 0x10, 0x09, 0x00, 0x09, 0x32, 0x15, 0xad, 0x05, 0xad, 0x32, 0x00, 0x00, 0x00, 0x00, 0x37, 0x03, 0x0b, 0x0b, 0x37, 0x00, 0x00, 0x00, 0x0c, 0x40);
dsi_dcs_write_seq(dsi, 0xd5, 0x19, 0x19, 0x18, 0x18, 0x1b, 0x1b, 0x1a, 0x1a, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x20, 0x21, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x24, 0x25, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
dsi_dcs_write_seq(dsi, 0xd6, 0x18, 0x18, 0x19, 0x19, 0x1b, 0x1b, 0x1a, 0x1a, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x25, 0x24, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x21, 0x20, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18);
dsi_dcs_write_seq(dsi, 0xe0, 0x00, 0x04, 0x0c, 0x12, 0x14, 0x18, 0x1a, 0x18, 0x31, 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f, 0x00, 0x04, 0x0c, 0x11, 0x13, 0x17, 0x1a, 0x18, 0x31, 0x3f, 0x4d, 0x4c, 0x54, 0x65, 0x6b, 0x70, 0x7f, 0x82, 0x7e, 0x8a, 0x99, 0x4a, 0x48, 0x49, 0x4b, 0x4a, 0x4c, 0x4b, 0x7f);
dsi_dcs_write_seq(dsi, 0xcc, 0x0b);
dsi_dcs_write_seq(dsi, 0xc0, 0x1f, 0x31);
dsi_dcs_write_seq(dsi, 0xb6, 0x7d, 0x7d);
dsi_dcs_write_seq(dsi, 0xd4, 0x02);
dsi_dcs_write_seq(dsi, 0xbd, 0x01);
dsi_dcs_write_seq(dsi, 0xb1, 0x00);
dsi_dcs_write_seq(dsi, 0xbd, 0x00);
dsi_dcs_write_seq(dsi, 0xc6, 0xed);

The panel's controller may or may not really be HX8394-F, because the panel's datasheet does list a number of controller options, and it's not clear which one is really used. Current kernel driver does not check the controller ID (if that's even possible).

The driver defines the mode as:

static const struct drm_display_mode hsd060bhw4_mode = {
        .hdisplay    = 720,
        .hsync_start = 720 + 40,
        .hsync_end   = 720 + 40 + 40,
        .htotal      = 720 + 40 + 40 + 40,
        .vdisplay    = 1440,
        .vsync_start = 1440 + 18,
        .vsync_end   = 1440 + 18 + 10,
        .vtotal      = 1440 + 18 + 10 + 17,
        .clock       = 66000, /*XXX: only 66MHz works */
        .flags       = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
        .width_mm    = 68,
        .height_mm   = 136,
};

This should match the parameters sent via the above initialization sequence. It's not really all that clear that it does match.

One of the more important initialization commands are:

They are important, because they need to correspond to the mode timings used by the kernel. They don't seem to. Vertical back/front porch values are off, other things may be off too. For example, some initialization sequence commands write beyond the end of the defined command parameter list, so it's not even clear that HX8394-F is really used, but not one of the other controllers specified as options in the LCD panel datasheet.

Hm? :(

It doesn't help that I can't find „HX8394-F application note“ that specifies how to correctly configure GIP source/gate driving circuitry to match the panel datasheet and our desired timings. The datasheet itslef glosses over all the details, just refering to unavailable application note for the details.

It may be useful to compare datasheets for other controllers listed in the panel datasheet, to check if one of them does match the initialization commands and their parameter counts better, or whether they explain relationships between GIP settings and hsync/vsync timing more properly.

I asked for more information about the panel in the Pine64 devzone. Until it's available, it will not be possible to achieve 60 Hz refresh rate. (without a lot of experimentation and research)

For easier experimentation not requiring a kernel re-compile for each display init sequence change, I'll extend the driver to allow changing and testing things over some custom debugfs interface.

Until this is solved, Pinephone Pro will have the same 60Hz video playback issues (unpleasant stutter due to mismatch between display refresh rate and the video frame rate) the original Pinephone had, until I fixed the refresh rate issue.