radxa / kernel

BSP kernel source
Other
152 stars 177 forks source link

Waveshare 10.1" LCD DSI on Rock 4B+ #328

Open BigMuscle85 opened 5 months ago

BigMuscle85 commented 5 months ago

I'm trying to make the Waveshare 10.1" LCD DSI to work on Rock 4B+ by porting the driver from Raspberry 6.1 kernel. I modified the code and the modules builds and loads properly. The image on LCD appears but it is shifted about 2 cm to the right (while the right edge overflows to the left) and colors are swapped. I'm trying to modify the timings but no luck. The display resolution is 1280x800.

Any advice how to fix the image misalignment? When comparing 7" RPi LCD driver code, I see the timings are a bit different in Radxa Kernel. When I tune the timings by this, it fixed the swapped colors but not the image position.

This is the display: https://www.waveshare.com/10.1inch-dsi-lcd-c.htm I'm using this code: https://github.com/raspberrypi/linux/blob/rpi-6.1.y/drivers/gpu/drm/panel/panel-waveshare-dsi.c

These are the timings that the driver uses on Raspberry Pi:

static const struct drm_display_mode ws_panel_10_1_mode = {
    .clock = 83333,
    .hdisplay = 1280,
    .hsync_start = 1280 + 156,
    .hsync_end = 1280 + 156 + 20,
    .htotal = 1280 + 156 + 20 + 40,
    .vdisplay = 800,
    .vsync_start = 800 + 40,
    .vsync_end = 800 + 40 + 48,
    .vtotal = 800 + 40 + 48 + 40,
};
BigMuscle85 commented 5 months ago

RaspberryPi driver originally used different timings which seems to be a bit better on Rock 4B+ - it does not swap the colors but the image is still shifted. It seems that the first line is not started at (0,0) which shifts the whole content. However, modifying the timings except of the resolution, clock and back-porch on total has absolutely no influence on the image. I.e. it makes no difference if I use 1280+40 or 1280+156.

https://github.com/raspberrypi/linux/commit/c7cf33911d477fe55a91a9e4d84dad857b244ae3

static const struct drm_display_mode ws_panel_10_1_mode = {
    .clock = 76800,
    .hdisplay = 1280,
    .hsync_start = 1280 + 40,
    .hsync_end = 1280 + 40 + 20,
    .htotal = 1280 + 40 + 20 + 40,
    .vdisplay = 800,
    .vsync_start = 800 + 40,
    .vsync_end = 800 + 40 + 48,
    .vtotal = 800 + 40 + 48 + 40,
};
BigMuscle85 commented 5 months ago

I managed to get it running. I am attaching the patch to include Waveshare driver in the kernel 5.10 and device tree overlay.

It uses gt9xx module for touch input which is included in the Radxa kernel. However, it seems that this module requires "touch-gpio" and "reset-gpio" pins to be defined else it results in long exception trace during the boot (but still works). But the Waveshare LCD does not use these pins. The module could be replaced with Goodix-TS driver which is also included but not enabled in Radxa kernel. This driver would require patching to support polling (+changing the name not to be in conflict with gt9xx driver).

0001-Add-panel-driver-for-Waveshare-DSI-touchscreens.patch 0001-Update-Goodix-touch-input-driver-to-support-polling.patch

Device tree overlay:

/dts-v1/;
/plugin/;

/ {
    metadata {
        title = "Enable Waveshare 10.1-inch Touchscreen on I2C6";
        compatible = "radxa,rockpi4a", "radxa,rockpi4b", "radxa,rockpi4c", "radxa,rockpi4a-plus", "radxa,rockpi4b-plus", "radxa,rock-4se";
        category = "display";
        exclusive = "dsi1";
        description = "Enable Waveshare 10.1-inch Touchscreen on I2C6";
    };

    fragment@0 {
        target = <&dsi>;

        __overlay__ {
            dsi1-only;
            status = "okay";
        };
    };

    fragment@1 {
        target = <&dsi1>;

        __overlay__ {
            rockchip,dsi-dsi0 = <&dsi>;
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;

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

                port@1 {
                    reg = <1>;
                    dsi_out_panel: endpoint {
                        remote-endpoint = <&panel_in_dsi>;
                    };
                };
            };
        };
    };

    fragment@2 {
        target = <&i2c6>;

        __overlay__ {
            status = "okay";
            #address-cells = <1>;
            #size-cells = <0>;

            waveshare_panel: waveshare-panel@45 {
                compatible = "waveshare,10.1inch-panel";
                reg = <0x45>;

                port {
                    panel_in_dsi: endpoint {
                        remote-endpoint = <&dsi_out_panel>;
                    };
                };
            };

            touch: goodix@14 {
                compatible = "goodix,gt9xx";
                reg = <0x14>;

                max-x = <800>;
                max-y = <1280>;
                tp-size = <910>;
            };
        };
    };

    fragment@3 {
        target = <&vopl_out_dsi1>;

        __overlay__ {
            status = "okay";
        };
    };

    fragment@4 {
        target = <&dsi1_in_vopb>;

        __overlay__ {
            status = "disabled";
        };
    };

    fragment@5 {
        target = <&dsi1_in_vopl>;

        __overlay__ {
            status = "okay";
        };
    };

    fragment@6 {
        target = <&route_dsi>;

        __overlay__ {
            status = "disabled";
            connect = <&vopl_out_dsi>;
        };
    };
};