Need Help setup Touch on LVDS Display

I’m asking for help setting up an LVDS touch display.
The display works with an adapter on the Apalis’ LVDS2.

I’d now like to add touch functionality.
I’m afraid the HYCON touch controller is connected to Apalis SPI0 I2C0 … that is, to pins 132 and 126, and in parallel to pins 211 and 209.
The carrier board is based on the Ixora carrier board.

My attempts to copy a dto together have failed.
Here is my attempt, which compiles and deploys but has no effect:

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2020-2021 Toradex
*/
// Enable a generic LVDS display on port 2.
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>

/dts-v1/;
/plugin/;
/ {
    compatible = "toradex,apalis-imx8";
};


/* I2C Bus, an dem der Touchcontroller angeschlossen ist (z.B. i2c1) */

&i2c1 {
    status = "okay";

    hycon_touch: touch@38 {
        compatible = "hycon,hy46xx"; // Replace with your controller's compatible string
        reg = <0x38>;  // 0111 000 0|1 0x38 OK?
        interrupt-parent = <&lsio_gpio2>;
        interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
        reset-gpios = <&lsio_gpio2 29 GPIO_ACTIVE_LOW>;
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
    };
};


&ldb2 {
...


...
...



tdx-info

Software summary
------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           5.15.148-6.7.0-devel+git.f437ddb7191d #1-TorizonCore SMP PREEMPT Mon Jul 1 08:03:31 UTC 2024
Kernel command line:      root=LABEL=otaroot rootfstype=ext4 quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3 ostree=/ostree/boot.1/torizon/9a5da750768d3006a86133f6bd7f2a2ee54a44dd2fca5f2e52ccb086cdf86784/0
Distro name:              NAME="TorizonCore"
Distro version:           VERSION_ID=6.7.0-devel-20240701080203-build.0
Distro variant:           VARIANT="Docker"
Hostname:                 apalis-imx8-07279028
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Apalis iMX8QM V1.1 on Apalis Ixora V1.2 Carrier Board
Toradex version:          0037 V1.1E
Serial number:            07279028
Processor arch:           aarch64
------------------------------------------------------------

Best
Gerald

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

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


Hello Gerald,

Thank you for the detailed information. Let’s break down your setup and where you might adjust things to enable touch functionality with your HYCON touch controller.

Key Points from Your Message

  • Display on LVDS2 is shown correctly.
  • HYCON touch controller is connected via SPI0 (not I2C) to Apalis pins 132 (MOSI), 126 (MISO), 211 (SCK), and 209 (CS).
  • Device tree overlay attempts so far have treated the controller as I2C (i2c1).
  • Running on TorizonCore 6.7.0-devel, Ixora carrier board V1.2.

1. Recognizing the Protocol

Your touch controller is connected via SPI, but your overlay is using I2C!
The block you wrote configures a hypothetical device on I2C1 at address 0x38, which won’t work, as the hardware is physically on SPI0, not I2C1.

For touch operation to work, we need:

  • a compatible driver for the HYCON controller over SPI
  • a correct device tree overlay, binding the controller node under the relevant &ecspi (SPI) node

2. Device Tree Overlay Example for SPI Touch

Let’s assume a generic approach here – since the actual HYCON driver may or may not be present in the Toradex kernel, but this is how you’d set up a SPI device:

/dts-v1/;
/plugin/;

/ {
    compatible = "toradex,apalis-imx8";
};

&ecspi1 { // Apalis SPI1 is on ecspi1
    status = "okay";

    hycon_touch: hycon@0 {
        compatible = "hycon,hy46xx"; // This must match the driver's expected string
        reg = <0>; // Chip Select 0 (use <1> for CS1)
        spi-max-frequency = <1000000>; // Touch controllers typically use up to 1MHz
        interrupt-parent = <&lsio_gpio2>;
        interrupts = <28 IRQ_TYPE_EDGE_FALLING>;  // Set to your INT GPIO
        reset-gpios = <&lsio_gpio2 29 GPIO_ACTIVE_LOW>; // Set to your RESET GPIO, if connected
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
    };
};

You’ll need to ensure:

  • The correct SPI bus and chip select are selected (ecspi1, and reg = <0> for CS0).
  • The pinmuxing for the used pins is properly set (sometimes this needs a pinctrl block).
  • The compatible string matches an available kernel driver; if not present, the device won’t be bound and show up.

3. Pin Mapping

  • Apalis SPI1 maps to ecspi1.
  • Pins 132/126/211/209 correspond to SPI MOSI/MISO/SCK/CS. You can cross-check this in the Apalis iMX8 datasheet.
  • lsio_gpio2 28 and 29 are exemplary for INT and RESET; ensure these match your circuit.

4. Check for Driver Availability

The line:

compatible = "hycon,hy46xx";

is only valid if this driver is available in your TorizonCore kernel. You can check this by running:

zcat /proc/config.gz | grep HYCON

or by looking at /sys/bus/spi/drivers/ to see if a suitable driver is present.

If there is no HYCON touch driver in the kernel, the overlay alone won’t work. Additional effort will be needed to supply such a driver, likely requiring kernel module development.


5. Additional Steps

  • Make sure the SPI bus and chip select are accessible and not already used by other peripherals.
  • Once the overlay is in place and deployed, check /dev/input/ for a new touch device when you boot.
  • You can also monitor dmesg with dmesg | grep spi or dmesg | grep -i touch to see if the device is detected and bound.

References


Summary:

  • Your overlay currently targets I2C, but hardware is on SPI.
  • Adjust overlay as above for SPI.
  • Confirm kernel driver support for your touch controller.
  • Monitor dmesg and /dev/input/ for device appearance.

If you provide the exact HYCON controller part number, I may be able to offer a more targeted configuration example.

Best regards,
Toradex AI Assistant.

OK, if I do this: zcat /proc/config.gz | grep HYCON
the response is:
# CONFIG_TOUCHSCREEN_HYCON_HY46XX is not set

looks like I have to use yocto.
:roll_eyes:

Hello @gerko,

Thanks for investigating this and reporting the results. We can enable this config for you in our following nightly builds. I am submitting a request to our Torizon R&D team to do that for you. Therefore, you don’t have to go through Yocto.

I will let you know once it is enabled.

Oh, that’s great.

However, I’m using a BSP already created in Yocto. My changes wouldn’t be included in the new nightly build.

And:

I can compile and add the Hycon driver as an external kernel module in TorizonCoreBuilder. I’ve now succeeded.

I’m afraid I still have a problem with the pin configuration for the interrupt and nRESET pins.

/* I2C Bus, an dem der Touchcontroller angeschlossen ist (z.B. i2c1) */
/* i2c2 is APALIS I2C1 ?? */
&i2c2 {
    status = "okay";

    hycon_touch: touch@38 {
        compatible = "hycon,hy46xx"; // Replace with your controller's compatible string
        reg = <0x38>;  // I2C-Adresse des Touchcontrollers
        interrupt-parent = <&lsio_gpio2>;
        interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
        reset-gpios = <&lsio_gpio2 29 GPIO_ACTIVE_LOW>;
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
		// pinctrl-names = "default";
		// pinctrl-0 = <&pinctrl_gpio_touch_interrupt>;
		status = "okay";

    };
};

is this correct … can this work or have I to define a pinctrl node?

I can compile and add the Hycon driver as an external kernel module in TorizonCoreBuilder. I’ve now succeeded.

That is indeed one way to do it. Glad to hear that you have succeeded in it.

In order to help you with the pin configuration for interrupt and reset signals, I need to know how you are connecting the touch controller to the Ixora Board. I am interested in knowing about what the physical connection looks like.

I hope the following screenshot is sufficient … ?

Hello @gerko,

Thanks for the schematics. I asked for it to compare it with our connections on the Ixora board for our LVDS display for Apalis iMX8QM. Looking into our default device tree I see (in imx8-apalis-ixora-v1.2.dtsi):

atmel_mxt_ts: touch@4a {
                compatible = "atmel,maxtouch";
                interrupt-parent = <&lsio_gpio4>;
                interrupts = <1 IRQ_TYPE_EDGE_FALLING>;         /* Apalis GPIO5 */
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_gpio5>, <&pinctrl_gpio6>;
                reg = <0x4a>;
                reset-gpios = <&lsio_gpio4 2 GPIO_ACTIVE_LOW>;  /* Apalis GPIO6 */
                status = "disabled";
        };

You can see this node and other relevant nodes enabled in the eoverlay file apalis-imx8_panel-cap-touch-10inch-lvds_overlay.dts.

Similarly, in your case you have to choose the right gpio as the interrupt-parent, create pinctrl for your touch controller etc. I see that you are using pins 183 and 181 for your RESET and INT signals. Have you created a pinctrl for your hycon touch using these? It should look something like:

pinctrl_hycon_touch: hycon_touch_pins {
        fsl,pins = <
            IMX8QM_ESAI0_TX2_RX3_LSIO_GPIO2_IO28 0x00000021 /* TOUCH.INT */
            IMX8QM_ESAI0_TX3_RX2_LSIO_GPIO2_IO29 0x00000021 /* TOUCH.nRESET */
        >;

Looking at the pins you use, the interrupt parent should be lsio_gpio2. These are some hints. I think you will have to try it based on our reference device tree.

Hello @gerko,

I have an update for you. The hycon touch control config support has been added to Torizon OS 7.4.0-devel-202508 version. You may test it on the latest nightly.

In the meantime, do you have any updates on the pin configuration topic?

Thank you!
I’m currently working on another problem.
I’ll let you know as soon as I’ve made progress.

Now I have the opportunity to continue working on the touch issue:
On the TorizonOS version 7, I can’t get the display to work with my LVDS overlay.
During ‘torizoncore-builder build’, I get the error message that the overlay doesn’t fit.

Therefore, I’m still trying to activate the touch on TOS 6.8.3 with the external hycon driver.Here are the corresponding code sections:

# file: linux/arch/arm64/boot/dts/freescale/imx8-apalis-ixora-v1.2.dtsi

// ...
/* Apalis I2C1 */


&i2c2 {
	status = "okay";

	// atmel_mxt_ts: touch@4a {
	// 	compatible = "atmel,maxtouch";
	// 	interrupt-parent = <&lsio_gpio4>;
	// 	interrupts = <1 IRQ_TYPE_EDGE_FALLING>;		/* Apalis GPIO5 */
	// 	pinctrl-names = "default";
	// 	pinctrl-0 = <&pinctrl_gpio5>, <&pinctrl_gpio6>;
	// 	reg = <0x4a>;
	// 	reset-gpios = <&lsio_gpio4 2 GPIO_ACTIVE_LOW>;	/* Apalis GPIO6 */
	// 	status = "enabled";
	// };

    hycon_touch: touch@38 {
        compatible = "hycon,hy46xx"; // Replace with your controller's compatible string
        reg = <0x38>;  // I2C-Adresse des Touchcontrollers
        interrupt-parent = <&lsio_gpio2>;
        interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
        reset-gpios = <&lsio_gpio2 29 GPIO_ACTIVE_LOW>;
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
		pinctrl-names = "default";
		pinctrl-0 = <&pinctrl_hycon_touch>;
		status = "enabled";
    };

// ...

// linux/arch/arm64/boot/dts/freescale/imx8-apalis-v1.1.dtsi

/* Apalis I2C1 */
&i2c2 {
	#address-cells = <1>;
	#size-cells = <0>;
	clock-frequency = <100000>;
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_lpi2c2>;
};

// ...

	/* Apalis I2C1 */
	pinctrl_lpi2c2: lpi2c2grp {
		fsl,pins =
			// <IMX8QM_GPT1_CLK_DMA_I2C2_SCL				0x04000020>,
			// <IMX8QM_GPT1_CAPTURE_DMA_I2C2_SDA			0x04000020>;
			<IMX8QM_LVDS1_I2C1_SCL_LVDS1_I2C1_SCL			0x04000020>,
			<IMX8QM_LVDS1_I2C1_SDA_LVDS1_I2C1_SDA			0x04000020>;
	};

// ...

	pinctrl_hycon_touch: hycon_touch_pins {
			fsl,pins = 
				<IMX8QM_ESAI0_TX2_RX3_LSIO_GPIO2_IO28 0x00000021>,
				<IMX8QM_ESAI0_TX3_RX2_LSIO_GPIO2_IO29 0x00000021>;
	};


and my lvds overlay:

// file: device-trees/overlays/apalis-imx8_lvds_touch_es.dts

// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2020-2021 Toradex
*/
// Enable a generic LVDS display on port 2.

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>

/dts-v1/;
/plugin/;
/ {
	compatible = "toradex,apalis-imx8", "toradex,apalis-imx8-v1.1";
};


&hycon_touch {
	status = "okay";
};


&ldb2 {
    status = "okay";

    lvds-channel@0 {
        status = "disabled";
    };

    lvds-channel@1 {
        fsl,data-mapping = "spwg";
        fsl,data-width = <24>;
        status = "okay";
        port@1 {
            reg = <1>;
            lvds2_out: endpoint {
                remote-endpoint = <&panel_lvds_in>;
            };
        };
    };
};

&ldb2_phy {
    status = "okay";
};

&panel_lvds {
    status = "okay";
    data-mapping = "vesa-24";
    width-mm = <155>;
    height-mm = <91>;
    panel-timing {
        clock-frequency = <25000000>;
        hactive = <800>;
        vactive = <480>;
        hback-porch = <8>;
        hfront-porch = <8>;
        vback-porch = <8>;
        vfront-porch = <8>;
        hsync-len = <4>;
        vsync-len = <4>;
        hsync-active = <0>;
        vsync-active = <0>;
        pixelclk-active = <0>;
    };
};

&panel_lvds_in {
    remote-endpoint = <&lvds2_out>;
};

&pwm_lvds1 {
    status = "okay";
};

ls /dev/apalis-i2c*
/dev/apalis-i2c-on-module  /dev/apalis-i2c1  /dev/apalis-i2c3

What next?
I don’t have an input device yet.

Update: have to define the concrete name that match in the driver: compatible = "hycon,hy4635";

Looks much better.
The Atmel Touch didn’t require a VCC?

The HYCON driver registers the touch, but doesn’t know what to do with it?

Now I have an event1 device under /dev/input.
Error -110 means there’s a timeout.
Looks like there’s something wrong with the I2C connection.
The device names i2c-2 … 4 are very confusing to me.

The result of i2cdetect -y 3 looks strange

Best
Gerald

Is there any chance that someone from Toradex will respond?

:face_with_peeking_eye:

Hi @gerko,

Sorry for the delay. It’s been a little busy time here.

From your schematics, it looks like you are using Apalis I2C1 interface ( pins SODIMM 209 and 211) - which should correspond to /dev/apalis-i2c1 in Linux, defined i2c2 in our standard device tree:

// file imx8-apalis-v1.1.dtsi
/* Apalis I2C1 */
&i2c2 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_lpi2c2>;
        #address-cells = <1>;
        #size-cells = <0>;
        clock-frequency = <100000>;
         ...
    };


/* Apalis I2C1 */
pinctrl_lpi2c2: lpi2c2grp {
    fsl,pins = <IMX8QM_GPT1_CLK_DMA_I2C2_SCL                        0x04000020>,  
               <IMX8QM_GPT1_CAPTURE_DMA_I2C2_SDA                    0x04000020>;
        };

I agree that these names are a little confusing to get around with. This article on I2C might help you : I2C (Linux) | Toradex Developer Center

Also, you can check the symlinks to i2c files like:

root@apalis-imx8-15445065:~# ls -al /dev/i2c*
crw------- 1 root root 89, 2 Oct  2 13:24 /dev/i2c-2
crw------- 1 root root 89, 3 Oct  2 13:24 /dev/i2c-3
crw------- 1 root root 89, 4 Oct  2 13:24 /dev/i2c-4
crw------- 1 root root 89, 5 Oct  2 13:24 /dev/i2c-5

root@apalis-imx8-15445065:~# ls -al /dev/apalis-i2c*
lrwxrwxrwx 1 root root 5 Oct  2 13:24 /dev/apalis-i2c-on-module -> i2c-3
lrwxrwxrwx 1 root root 5 Oct  2 13:24 /dev/apalis-i2c1 -> i2c-4
lrwxrwxrwx 1 root root 5 Oct  2 13:24 /dev/apalis-i2c3 -> i2c-5

Usually, to define how Linux enumerates these I2C files, aliases are used in the device tree. However, for the apalis iMX8QM, I see no aliases for i2c starting from i2c2 are defined, in which case the kernel assigns them a name in ascending order - ie, in this case, enumerated starting from i2c2. To find out which i2c from the linux side corresponds to which one in the device tree, you can use the following trick (where you will find it based on the bus address):

root@apalis-imx8-15445065:~# find /sys/devices/platform/ -name i2c-*
/sys/devices/platform/bus@5a000000/5a810000.i2c/i2c-3
/sys/devices/platform/bus@5a000000/5a810000.i2c/i2c-3/i2c-dev
/sys/devices/platform/bus@5a000000/5a810000.i2c/i2c-3/i2c-dev/i2c-3
/sys/devices/platform/bus@5a000000/5a830000.i2c/i2c-5
/sys/devices/platform/bus@5a000000/5a830000.i2c/i2c-5/i2c-dev
/sys/devices/platform/bus@5a000000/5a830000.i2c/i2c-5/i2c-dev/i2c-5
/sys/devices/platform/bus@5a000000/5a800000.i2c/i2c-2
/sys/devices/platform/bus@5a000000/5a800000.i2c/i2c-2/i2c-dev
/sys/devices/platform/bus@5a000000/5a800000.i2c/i2c-2/i2c-dev/i2c-2
/sys/devices/platform/bus@5a000000/5a820000.i2c/i2c-4
/sys/devices/platform/bus@5a000000/5a820000.i2c/i2c-4/i2c-dev
/sys/devices/platform/bus@5a000000/5a820000.i2c/i2c-4/i2c-dev/i2c-4

In your device tree, you are using i2c2 node for your touch controller - which is defined as:
i2c2: i2c@5a820000 in linux-toradex/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi. This gives you the indication that it is enumerated as i2c-4 - which /dev/apalis-i2c1 is symlinked to.

I think you should check i2cdetect -y 4.

I am not sure about why it shows error -110. I will ask a colleague who is more expert and get back to you.

Hi @gerko,

I just discussed with a colleague about this. One thing that you are doing wrong is creating a pinctrl for i2c2 node with pins that are driven by the controller for i2c1_lvds1. Therefore, if you want to use pins 132 and 126, you should use i2c1_lvds1 node instead of i2c2 node. It would look like this:

&i2c1_lvds1:  {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c1_lvds1>;
    
    hycon_touch: touch@38 {
        compatible = "hycon,hy46xx"; // Replace with your controller's compatible string
        reg = <0x38>;  // I2C-Adresse des Touchcontrollers
        interrupt-parent = <&lsio_gpio2>;
        interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
        reset-gpios = <&lsio_gpio2 29 GPIO_ACTIVE_LOW>;
        touchscreen-size-x = <800>;
        touchscreen-size-y = <480>;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hycon_touch>;
        status = "okay";
    };
};


pinctrl_lpi2c2: lpi2c2grp {
    fsl,pins =
		<IMX8QM_LVDS1_I2C1_SCL_LVDS1_I2C1_SCL			0x04000020>,
		<IMX8QM_LVDS1_I2C1_SDA_LVDS1_I2C1_SDA			0x04000020>;
};

pinctrl_hycon_touch: hycon_touch_pins {
	fsl,pins = 
		<IMX8QM_ESAI0_TX2_RX3_LSIO_GPIO2_IO28           0x00000021>,
		<IMX8QM_ESAI0_TX3_RX2_LSIO_GPIO2_IO29           0x00000021>;
};

Also, all of this needs to be in your device tree overlay. You can modify the device tree of course, but it is not the recommended approach.
I also noticed that you have status = "enabled" in your device tree, which is wrong. I am surprised that it compiles. May be you could try to introduce an error in the device tree before you compile to see if it actually compiles.

Thank you very much!

I think this line

should result in the new node: pinctrl_i2c1_lvds1

in the overlay I had to add the 2 new nodes in this reference:
&iomuxc {
pinctrl_i2c1_lvds1: i2c1_lvds1_pins {

};
is that right?

Now I get the following messages when I touch the display:
torizon@apalis-imx8-07202014:~$ dmesg -w | grep hycon
[ 61.641606] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0x4c
[ 61.661854] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.675396] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.689375] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.702914] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.716936] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.730483] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.744288] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.757808] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 61.771664] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xcc
[ 87.736568] hycon_hy46xx_check_checksum: 6 callbacks suppressed
[ 87.736595] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0x3f
[ 87.756478] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xbf
[ 87.770034] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xbf
[ 87.783836] hycon_hy46xx 5-0038: checksum error: 0x00 expected, got 0xbf

I can comment out the following lines of code in the driver:

if (!hycon_hy46xx_check_checksum(tsdata, rdbuf)) goto out;

The touch functionality then works perfectly.
But it would be better if the checksum check worked properly. ?

Thanks again
Gerald

Update:

I am now using the touch controller without checksum verification. So far, I haven’t been able to detect any problems in this regard.

With your help, I consider the matter resolved for now… thank you.

1 Like

Hello @gerko,

That’s right, you need to add the pinctrl into the iomuxc node, so the IOMUX controller will apply the alternate functions for these pins.

Regarding the error messages about checksum:
Normally, the driver calculates the checksum for the received data packet on the I2C bus and compares it against the checksum sent by the touch controller. The messages you receive indicate that these don’t match. In such cases, usually the driver would ignore the input and logs these warning messages. Since you mentioned that the the touch functionality works perfectly when you comment out the checksum validation, it implies that the data itself is valid. Only the checksum function in the driver is failing. So it is most likely a wrong checksum calculation algorithm for the driver, or this Hycon touch controller model behaves differently. I would say, as a short-term solution, commenting out that function call in the driver is good enough. But checking the datasheet of this Hycon controller to understand the checksum validation and comparing it against the actual function definition would be the way to go.