fbdev and ssd1306

I am trying to get the kernel driver for the ssd1306 working with the PocketBeagle USB HUB cape which has a 64x32 SSD1306 display (https://www.tindie.com/products/microwavemont/oled-with-24-port-usb-hub-cape-for-pocketbeagle/) I know it is physically working as I can use it via user-mode I2C. I believe a small change is needed to support the unusual 64 pixel width of this board. I have built and loaded a new kernel and have a .dtbo loaded via u-boot with 4.4.88-ti-r128 kernel. It shows up in /proc/device-tree correctly (at least as far as I can tell - the entries match the dts values). I am missing how to get this connected to the framebuffer world - there is no /dev/fb0 showing up. I see the config options appear to be enabled (I am using the defconfig). My googling did not turn up anything other than others stuck in a similar situation on RPi’s.

Mark

I am trying to get the kernel driver for the ssd1306 working with the PocketBeagle USB HUB cape which has a 64x32 SSD1306 display (https://www.tindie.com/products/microwavemont/oled-with-24-port-usb-hub-cape-for-pocketbeagle/) I know it is physically working as I can use it via user-mode I2C. I believe a small change is needed to support the unusual 64 pixel width of this board. I have built and loaded a new kernel and have a .dtbo

And what does your device tree overlay look like?

loaded via u-boot with 4.4.88-ti-r128 kernel. It shows up in /proc/device-tree correctly (at least as far as I can tell - the entries match the dts values). I am missing how to get this connected to the framebuffer world - there is no /dev/fb0 showing up. I see the config options appear to be enabled (I am using the defconfig).

And which options did you enable/are enabled?

I am trying to get the kernel driver for the ssd1306 working with the PocketBeagle USB HUB cape which has a 64x32 SSD1306 display (https://www.tindie.com/products/microwavemont/oled-with-24-port-usb-hub-cape-for-pocketbeagle/) I know it is physically working as I can use it via user-mode I2C. I believe a small change is needed to support the unusual 64 pixel width of this board. I have built and loaded a new kernel and have a .dtbo

And what does your device tree overlay look like?

/dts-v1/;
/plugin/;

#include <dt-bindings/board/am335x-bbw-bbb-base.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>

/ {
fragment@0 {
target = <&i2c1>;
overlay {
status = “okay”;

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

ssd1306: oled@3c {
compatible = “solomon,ssd1306fb-i2c”;
reg = <0x3c>;
solomon,width = <64>;
solomon,height = <32>;
solomon,page-offset = <0>;
};
};
};
};

loaded via u-boot with 4.4.88-ti-r128 kernel. It shows up in /proc/device-tree correctly (at least as far as I can tell - the entries match the dts values). I am missing how to get this connected to the framebuffer world - there is no /dev/fb0 showing up. I see the config options appear to be enabled (I am using the defconfig).

And which options did you enable/are enabled?

mark@pocket:~$ zcat /proc/config.gz | grep CONFIG_FB | grep -v ‘#’
CONFIG_FB=y
CONFIG_FB_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_IMAGEBLIT=y
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_DEFERRED_IO=y
CONFIG_FB_BACKLIGHT=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
CONFIG_FB_SMSCUFX=m
CONFIG_FB_UDL=m
CONFIG_FB_SIMPLE=y
CONFIG_FB_SSD1307=y

Looks alright to me. Is there any error in `dmesg`?

mark@pocket:~$ dmesg | grep -P ‘fb|ssd’
[ 2.165499] ssd1307fb 1-003c: failed to get VBAT regulator: -19

How does fbdev “find” the ssd1306?

mark@pocket:~$ dmesg | grep -P ‘fb|ssd’
[ 2.165499] ssd1307fb 1-003c: failed to get VBAT regulator: -19

How does fbdev “find” the ssd1306?

Question doesn’t quite make sense to me, but these fbtft drivers depend on and implement interfaces for fbdev, so it is by direct reference from the driver.

More below…

I am trying to get the kernel driver for the ssd1306 working with the PocketBeagle USB HUB cape which has a 64x32 SSD1306 display (https://www.tindie.com/products/microwavemont/oled-with-24-port-usb-hub-cape-for-pocketbeagle/) I know it is physically working as I can use it via user-mode I2C. I believe a small change is needed to support the unusual 64 pixel width of this board. I have built and loaded a new kernel and have a .dtbo

And what does your device tree overlay look like?

/dts-v1/;
/plugin/;

#include <dt-bindings/board/am335x-bbw-bbb-base.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/am33xx.h>

/ {
fragment@0 {
target = <&i2c1>;
overlay {
status = “okay”;

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

ssd1306: oled@3c {
compatible = “solomon,ssd1306fb-i2c”;
reg = <0x3c>;
solomon,width = <64>;
solomon,height = <32>;
solomon,page-offset = <0>;

I don’t see VBAT specified. Kinda odd that it’s default would cause a conflict. You might look at the device tree properties to see how it gets set.

To avoid pin conflicts, I took the approach of creating a new dtb built using an include base file for my board with an fbtft display. https://github.com/RobertCNelson/dtb-rebuilder/blob/4.14-ti/src/arm/am335x-pocketbeagle-simplegaming.dts

A bit of looking at what VBAT is…
https://patchwork.kernel.org/patch/9515011/

Finally noticing this is a regulator, I would personally start out being lazy and grabbing an already existing static-on regulator like vmmcsd_fixed from https://github.com/RobertCNelson/dtb-rebuilder/blob/4.4-ti/src/arm/am335x-pocketbeagle-common.dtsi.

The linux driver for this is an i2c driver. So the device tree node that you added will create an i2c device in the linux kernel (i.e. /sys/bus/i2c/devices/1-003c). Then udev sees that this device matches the compatible string of the “ssd1307fb” driver (you will see this listed in lsmod). This driver is bound to the device and calls the drivers probe function. This is where the error message is coming from. If the probe function had completed successfully, it would have registered a new fbdev device.

It looks like this error is a bug in the linux kernel that was fixed in kernel v4.11. .

You can work around this by adding a fixed regulator to the device tree and adding it to your device. Or, if you are compiling your own kernel anyway, you can grab the patch I linked.

Thanks. That was a bit embarrassing - I saw the message in dmesg but assumed it was benign since the /proc/device-tree entry was there. I’ll move to a later kernel and try my fix there. I appreciate your quick help!

Mark

I moved 4.14.12-ti-r24 and now it gets past the the vbat regulator, but then fails trying to write to the I2C with a bus ready timeout:

mark@pocket:~/bb.org-overlays/src/arm$ dmesg | grep -P ‘ssd|i2c’
[ 0.508117] omap_i2c 44e0b000.i2c: could not find pctldev for node /ocp/l4_wkup@44c00000/scm@210000/pinmux@800/pinmux_i2c0_pins, deferring probe
[ 0.509098] omap_i2c 4802a000.i2c: bus 1 rev0.11 at 400 kHz
[ 0.509821] omap_i2c 4819c000.i2c: bus 2 rev0.11 at 400 kHz
[ 1.945474] omap_i2c 4802a000.i2c: timeout waiting for bus ready
[ 1.945496] ssd1307fb 1-003c: Couldn’t send I2C command 2.
[ 1.945554] ssd1307fb: probe of 1-003c failed with error -110
[ 2.057076] i2c /dev entries driver
[ 2.178366] input: tps65217_pwr_but as /devices/platform/ocp/44e0b000.i2c/i2c-0/0-0024/tps65217-pwrbutton/input/input0
[ 2.179568] omap_i2c 44e0b000.i2c: bus 0 rev0.11 at 400 kHz

After the boot finishes, I can use the device from userspace with no problems. It seems that i2c-1 is registered before the ssd1307fb probe happens. Are pins not assigned at this point?

Mark

Sounds like a question for RCN. I'm not up to speed on the pinctrl situation on BeagleBone. I'm weird and don't use capemanager or any of the usual BealgeBone stuff.

But, I think you are right to think the problem is cause by pin muxing somehow.

Thanks, David. I am not competent enough on DT yet. I see one of the I2C devices has a pinctrl in the device-tree but i2c1 does not. I don’t understand why/how when I open /dev/i2c-1 from userspace that the pins seem to get assigned. Hopefully Robert can help.

Mark

Perhaps something is changing the pinmux later in boot. I'm not seeing anything for i2c1, but there is an overlay for i2c2. https://github.com/beagleboard/linux/blob/4.14/arch/arm/boot/dts/am335x-bone-pinmux-i2c2.dtsi

You should be able to add this to your overlay and modify it for i2c1. Then the pins should get muxed before the i2c driver tries to load.

Thanks, David. We were on the right track. I tried something similar but failed. I believe it’s because the base dtb for the pocket has already assigned the p2_09 and p2_11 pins to the universal pinmux. I went back to the base dts and deleted the universal entries and setup a new i2c1_pins mapping and used those in setting up &i2c1 - success!

mark@pocket:~$ dmesg | grep fb
[ 1.304882] ssd1307fb 1-003c: fb0: Solomon SSD1307 framebuffer device registered, using 256 bytes of video memory
mark@pocket:~$ fbset -i

mode “64x32”
geometry 64 32 64 32 1
timings 0 0 0 0 0 0 0
rgba 1/0,1/0,1/0,0/0
endmode

Frame buffer device information:
Name : Solomon SSD1307
Address : 0x9b637000
Size : 256
Type : PACKED PIXELS
Visual : MONO10
XPanStep : 0
YPanStep : 0
YWrapStep : 0
LineLength : 8
Accelerator : No

The console now shows up at boot, but the text is reversed/mirror image. Is there a fbdev option to remap the display? I am googling around but have not seen anything yet …

Mark

Thanks, David. We were on the right track. I tried something similar but failed. I believe it's because the base dtb for the pocket has already assigned the p2_09 and p2_11 pins to the universal pinmux. I went back to the base dts and deleted the universal entries and setup a new i2c1_pins mapping and used those in setting up &i2c1 - success!

Great!

The console now shows up at boot, but the text is reversed/mirror image. Is there a fbdev option to remap the display? I am googling around but have not seen anything yet ...

No, but there is solomon,com-invdir in the device tree bindings.

Turns out that solomon,segment-no-remap fixed it. I’ll confess the descriptions and datasheet leave me a little puzzled, but for now it works - see the attached photo. I also added a new solomon,col-offset to enable offsetting the “window” of the smaller 64x32 OLED in the actual 128x64 pixel RAM of the SSD1306. Reading various posts around the web, each controller + OLED can be connected in different ways so the flexibility of both column and page offsets is needed. I’ll try submitting a patch for the ssd1307fb.c driver.

Thanks again for the help.

Mark
pb_ssd1306.jpg