Kernel module didn't get built, any logs as to why?

Hi everyone! I tried to add a module to the kernel and then build CE. While the CE image gets built and is working fine the kernel module I added is missing. Is there a log somewhere that tells me why the module didn’t get built?

I’m a beginner just playing around so any help is appreciated. :slight_smile:

How did you add/enable this module? Did you modify file projects/Amlogic-ng/linux/linux.aarch64.conf ?

Read this

1 Like

Thanks! You were spot on. :slight_smile: Now building fails on the module I want to add so time for some trial and error.

Alright, so the module I’m trying to add is gpio-ir-tx, which is included in linux 4.14 and up. I managed to get it built in linux-amlogic 4.9 with some dirty hacking in rc-core related files, without knowing C so I’m fairly certain the module won’t even work in the state I compiled it in but I would like to test it anyways. I put my modifications up on Github if anyone feels like checking it.

Anyways, to test the module I need to define a GPIO pin for it in my dVIM3’s device tree file as per the documentation over here. Can somebody show me the right way to do this either in the device tree source (VIM3 dts file over here) or from commandline using fdtput (which is suited for this purpose, right?)?

Try with pin 39 GPIODZ_15

	irled@0 {
		compatible = "gpio-ir-tx";
		gpios = <&gpio GPIOZ_15 GPIO_ACTIVE_HIGH>;
1 Like

Thanks, I added that to the device tree source and built a new CE image (confirmed binding by decompiling dtb.img with dtc). But I don’t see another lirc device for sending IR signals. Just the standard /dev/lirc0 and it can only be used for receiving (not sending):

# ir-ctl -f -d /dev/lirc0
Receive features /dev/lirc0:
 - Device can receive raw IR
warning: /dev/lirc0: device supports setting receiving timeout but min timeout is 0
 - Can set receiving timeout min:0 microseconds max:1250000 microseconds
Send features /dev/lirc0:
 - Device cannot send

I can see the gpio-ir-tx module on my system:

# modinfo gpio-ir-tx
filename:       /lib/modules/4.9.113/kernel/drivers/media/rc/gpio-ir-tx.ko
license:        GPL
author:         Sean Young <>
description:    GPIO IR Bit Banging Transmitter
alias:          of:N*T*Cgpio-ir-txC*
alias:          of:N*T*Cgpio-ir-tx
depends:        rc-core
intree:         Y
vermagic:       4.9.y SMP preempt mod_unload aarch64

Could you just confirm that I put the device tree binding in the right place in the dts file? Because then I can just assume that I broke the module with my source code modifications. That would explain why it can’t create a /dev/lirc1 device.

Here’s the full g12b_a311d_khadas_vim3.dts file:

#include "coreelec_g12b.dtsi"

	model = "Khadas VIM3";
	amlogic-dt-id = "g12b_kvim3";
	coreelec-dt-id = "g12b_a311d_khadas_vim3";

	/delete-node/ memory@00000000;

	gpioleds {
		status = "okay";

		sys_led {
			gpios=<&gpio_ao GPIOAO_4 GPIO_ACTIVE_HIGH>;

		red_led {
			label = "red_red";
			gpios = <&gpio_expander 5 GPIO_ACTIVE_HIGH>;
			default-state ="off";

	cvbsout {
		/delete-property/ clk_path;

	gpio_keypad {
		key-gpios = <&gpio_ao GPIOAO_7 GPIO_ACTIVE_HIGH>;

	adc_keypad {
		compatible = "amlogic, adc_keypad";
		status = "okay";
		key_name = "home";
		key_num = <1>;
		io-channels = <&saradc SARADC_CH2>;
		io-channel-names = "key-chan-2";
		key_chan = <SARADC_CH2 SARADC_CH2 SARADC_CH2>;
		key_code = <102>;
		key_val = <108>; //val=voltage/1800mV*1023
		key_tolerance = <40>;

	efuse: efuse {
		compatible = "amlogic, efuse";
		read_cmd = <0x82000030>;
		write_cmd = <0x82000031>;
		get_max_cmd = <0x82000033>;
		key = <&efusekey>;
		status = "okay";

	/delete-node/ efusekey;
	efusekey: efusekey {
		keynum = <1>;
		key0 = <&key_0>;
			keyname = "mac";
			offset = <0>;
			size = <6>;

	amlvecm {
		interrupts = <0 56 1>;
		interrupt-names = "vsync2";
	irled@1 {
		compatible = "gpio-ir-tx";
		gpios = <&gpio GPIOZ_15 GPIO_ACTIVE_HIGH>;

	/delete-node/ rtc;

&audiobus {
	aml_spdif: spdif {
		pinctrl-names = "spdif_pins", "spdif_pins_mute";
		pinctrl-0 = <&spdifout>;
		pinctrl-1 = <&spdifout_a_mute>;

&pinctrl_periphs {
	/delete-node/ spdifout;
	/delete-node/ spdifout_a_mute;

&pinctrl_aobus {
	spdifout: spdifout {
		mux {
			groups = "spdif_out_ao";
			function = "spdif_out_ao";

	spdifout_a_mute: spdifout_a_mute {
		mux {
			groups = "GPIOAO_10";
			function = "gpio_aobus";

&i2c0 {
	/delete-property/ pinctrl-names;
	/delete-property/ pinctrl-0;
	/delete-property/ clock-frequency;

&i2c2 {
	status = "disabled";
	/delete-property/ pinctrl-names;
	/delete-property/ pinctrl-0;
	/delete-property/ clock-frequency;

&i2c3 {
	status = "okay";
	clock-frequency = <100000>;

&i2c_AO {
	status = "okay";
	clock-frequency = <400000>;

	gpio_expander: gpio-controller@20 {
		compatible = "ti,tca6408";
		reg = <0x20>;
		#gpio-cells = <2>;
		status = "okay";

	hym8563: hym8563@51 {
		compatible = "haoyu,hym8563";
		reg = <0x51>;
		#clock-cells = <0>;

	khadas-mcu {
		compatible = "khadas-mcu";
		reg = <0x18>;
		fan,trig_temp_level0 = <50>;
		fan,trig_temp_level1 = <60>;
		fan,trig_temp_level2 = <70>;
		hwver = "VIM3.V11";

&pwm_ef {
	pinctrl-names = "default";
	pinctrl-0 = <&pwm_f_pins2>;

&usb2_phy_v2 {
	gpio-vbus-power = "GPIOA_6";
	gpios = <&gpio GPIOA_6 GPIO_ACTIVE_HIGH>;

&usb3_phy_v2 {
	/delete-property/ gpio-vbus-power;
	/delete-property/ gpios;
	otg = <1>;

&pcie_A {
	reset-gpio = <&gpio GPIOA_8 GPIO_ACTIVE_HIGH>;
	status = "disabled";

&saradc {
	status = "okay";

&spicc1 {
	status = "disabled";
	pinctrl-names = "default";
	pinctrl-0 = <&spicc1_pins>;
	cs-gpios = <&gpio GPIOH_6 GPIO_ACTIVE_HIGH>;

	spidev@0 {
		status = "disabled";
		compatible = "linux,spidev";
		/* spi default max clock 100Mhz */
		spi-max-frequency = <100000000>;
		reg = <0>;

DTS seems ok to me.

Did you tried to load module by hand?

modrobe gpio-ir-tx

and then post dmesg log

dmesg | paste
1 Like

Thanks, I’ve been playing around again. lsmod shows the module:

gpio_ir_tx             16384  0
rc_core                36864  8 ir_rc6_decoder,ir_nec_decoder,gpio_ir_tx,ir_lirc_codec,meson_ir,lirc_dev

And here’s the dmesg paste on a clean boot, which shows an error with the module:

[    3.106706@3] gpio-ir-tx irled@1: failed to register rc device
[    3.106719@3] gpio-ir-tx: probe of irled@1 failed with error -22

That error comes from the module source gpio-ir-tx.c at line 183.

I took the gpio-ir-tx.c from a newer kernel and had to make a few changes to the source right around the part that that takes care of registering the rc device (because devm_rc_allocate_device and devm_rc_register_device don’t exist in kernel 4.9 and work with their counterparts without devm_ prefix. To make the changes I looked at gpio-ir-recv.c and copied parts of the code from there.

Any suggestions on how to fix this and get the rc device to register properly?

P.S. when booting my VIM3 with the non-modified dtb the module is not loaded unless I manually load it with modprobe, and then it’s only visible as using rc_core module (nothing in dmesg either):

rc_core                36864  7 ir_rc6_decoder,ir_nec_decoder,gpio_ir_tx,ir_lirc_codec,meson_ir,lirc_dev

Error -22 is EINVAL “Invalid argument” because you didn’t set rcdev->map_name.

So start with that.

1 Like

Right again, that resolved the error, new dmesg output shows:

[    3.227292@0] Registered IR keymap rc-empty
[    3.227535@0] input: GPIO IR Bit Banging Transmitter as /devices/virtual/rc/rc0/input6
[    3.227726@0] rc rc0: GPIO IR Bit Banging Transmitter as /devices/virtual/rc/rc0

But I must say, the more I look at the code the more I think the entire gpio_ir_tx_probe function needs to be rewritten. When gpio-ir-tx was added to the kernel an overhaul was done to rc-core as well, simplifying the individual drivers. If you compare the probe function from gpio-ir-recv from 4.9 with 4.14 you can see how it was rewritten for that module as well.

I’m afraid this is over my head unfortunately. But if you have any more (easy) suggestions I would love to hear them of course.

I don’t see much changes and should probably work. Maybe some little changes are missing.
Did you test if it works? How to transmit something? And what hw is needed? Maybe I could play with it.

You could also look lirc which also supports transmitter.

1 Like

Yes, I tested by building the entire image and updating my VIM3 with it but there is no new lirc device so I can’t transmit anything. As you can see in my previous post dmesg output mentions /devices/virtual/rc/rc0 (but that path doesn’t exist).

If you’re willing to test things: in terms of hardware all that’s needed is an IR LED with a resistor (or a regular LED to visually check if it’s working) connected to the GPIO pin. As I understand it, when the module is working, a new /dev/lirc device is supposed to show up that can be used to send IR commands. The lirc device can be checked with ir-ctl -f -d /dev/lirc1. Commands can easily be sent like ir-ctl -d /dev/lirc1 -S nec:0x810.

Maybe it’s also useful to know that Raspberry Pi’s (that run an updated kernel) have this module out of the box and there it can be enabled with a simple device tree overlay setting, e.g. on LibreELEC (it’s the same for gpio-ir-tx and pwm-ir-tx).

Regarding the reason the module is not working: there may also be an issue with dependencies, for example in rc-main.c there are no references to RC_DRIVER_IR_RAW_TX at all. Which are added in kernel 4.14. And if you browse the kernel source at the commit that added gpio-ir-tx it is also visible that a lot of changes were made to various files dealing with IR and the rc-core.

Anyways I forked linux-amlogic and CoreELEC and put my attempt up on Github in separate branches. So you could just download branch CE-9.2-with-ir-tx of my CoreELEC fork and it will automatically get the modified kernel as well.

Seems it is not just this module but few other pieces around rc subsystem. You should look commits from 4.9 to rc and took everything in regards to rc.

About | FAQ | Terms of Service | Privacy Policy | Legal Notice