We’ve just uploaded a new image of Android Jellybean for our BD-SL-i.MX6, Nitrogen6x, and for the first time, our new Nitrogen6 Max board.
This will be a lengthy post because it covers the details of a number of new features, and describes in some detail how the features of the our new Nitrogen6 Max board are made available.
For the impatient
You can download the image from here:
As usual, you’ll need to register on our site and agree to the EULA because it contains Freescale content. The image is a 4GB SD card image that can be restored using zcat and dd under Linux or Alex Page’s USB Image Tool under Windows.
The sources for this release are in the boundary-imx_jb4.3_1.0.0-ga branch of our Github repository (the main development branch), and the build steps are otherwise the same as in the second beta release.
We have added one additional component, the can-utils project for use in testing the CAN bus.
The primary enhancements in this image (aside from 6 Max support) include:
- Additional display and touch screen support.
- Dual camera support.
- Support for HDMI and SDI receiver inputs through the camera interfaces.
- Updates to allow easy loading of on-board eMMC
Features that are specific to the Nitrogen6 Max board include:
- Dual (separate) LVDS display support
- Dual-channel LVDS display support for resolutions up to 1080P
- RS-232/RS-485 support on UART5
- There are some quirks related to the 4GiB of RAM on Nitrogen6 Max
Display and touch screen changes
Since the previous release of Jellybean, we’ve added support for touch controllers from Goodix and Ilitek, and increased the functionality of our FocalTech touch controllers.
Our 7″ 1024×600, 7″ 1280×800 and 10.1″ 1280×800 displays now support 12-point touch instead of the original 5-point touch in the original driver.
The Ilitek touch controller is used in our new 10.1″ sunlight-readable display.
Dual camera support
This feature has been a long time in coming, but for those of you using our 5 mega-pixel OV5640 MIPI camera, life is a bit easier.
Because our two primary camera modules shared an I2C bus and had the same address, previous releases required kernel re-compilation to swap between them. For this release, the Linux kernel drivers now reassign the I2C addresses during startup, allowing connection of both cameras simultaneously, and map the MIPI camera to the Back camera and the parallel camera to the Front camera in Android jargon.
Probably most importantly, this allows us to ship a single kernel image with both cameras enabled, so MIPI users don’t have to re-compile or re-name files before using the camera.
Additional video inputs
Beside cameras, this release contains kernel support for a number of additional video input devices:
- TC358743 HDMI to MIPI bridge,
- Semtech GS2971 SDI Receiver,
Techwell/Intersil 68xx Video Decoders (PCI Express Media Bridge)
- Analog Devices ADV7180 SDTV Video Decoder
Because these devices don’t map readily to the simple Front Camera/Rear Camera model provided by Android, these devices are not currently supported by the Android HAL, and require customized Android builds in order to use them.
In an earlier post, we provided a customized kernel and RAM disk that turned our BD-SL-i.MX6 or Nitrogen6X boards into a very expensive SD card reader by using the g_mass_storage gadget.
This release extends that to support the Nitrogen6 Max board, and also updates the boot script to invoke this automatically if the Volume Down key on our Android button board is pressed during boot.
If you don’t have an Android button board, you can short pins 7 and 8 of J14 with a paper clip (these pins are Volume down and Ground respectively).
Note that this feature is not specific to eMMC or to the Nitrogen6 Max board. It is also very handy for loading SATA drives or even SD cards.
The /init script in the RAM disk walks through and exposes each block device found on the system, making it available over the USB OTG port
The two files involved (uImage-recovery and uramdisk-recovery.img) can also be copied to a TFTP server and loaded by U-Boot using the usbrecover command as described in the release notes for U-Boot 2014.04.
CAN bus utilities
As mentioned earlier, we’ve included the can-utils package in this release. While we don’t have a lot of experience with CAN, we have tested this by connecting multiple of our boards together, and using cansend and candump as follows:
# on both boards: root@nitrogen6x:/ # ip link set can0 up type can bitrate 125000 root@nitrogen6x:/ # candump can0 & root@nitrogen6x:/ # cansend can0 5A1#188.8.131.52.184.108.40.206 can0 5A1  11 22 33 44 55 66 77 88
The Nitrogen6 Max board has a third serial port, which is software-selectable to support either RS-232 or RS-485 signalling. It is connected to UART5 on the processor, and exposed as /dev/ttymxc4 under Linux.
By default, the port is configured for RS-232. In order to configure it for RS-485, you can write to an entry in sysfs:
root@nitrogen6x:/ # echo 1 > /sys/devices/platform/imx-uart.4/rs485_en
If a board will be at the end of an RS-485 chain, you may also need to use SW5 to enable a termination resistor. There are silk screen labels showing the positions, and RS-485 means terminated as shown in the photo.
Dual independent LVDS
One of the primary features of the Nitrogen6 Max board is the addition of a second LVDS channel, that can be used to drive either two separate displays or a single, high-resolution display.
Neither one of these is truly plug and play, and some effort is required to make use of them in this Android release.
To begin with, only a single panel (LVDS0 on the bottom side of the Nitrogen6 Max) is supported in U-Boot, and this must be defined as the primary display.
Since our boards only have a single I2C connector (J7) for use in connecting a touch screen, we can only detect one touch controller. Even if we did detect multiple displays, we have no way of knowing which you’d want to be the primary display. (You may not be aware of this, but the Android support for multiple displays uses the primary (/dev/graphics/fb0) display to define the screen resolution for applications and simply mirrors and scales the content to the secondary display)
The configuration process is simple though. You enable the second display by inserting multiple video= clauses with the dev=ldb flag to the bootargs variable in U-Boot.
For example, this fragment will configure our 1280×800 panel as the primary and a 1024×600 panel as the secondary display:
You will need a custom boot script for this.
The next issue related to dual independent LVDS displays is the backlight. The Android userspace only has support for a single brightness control, and we have this connected to PWM4 to control the brightness of the primary panel (i.e. same as BD-SL-i.MX6 and Nitrogen6x).
The second LVDS port has its’ backlight control on PWM3, and the only way you can control it is through sysfs:
root@nitrogen6x:/ # echo 255 > /sys/class/backlight/pwm-backlight.2/brightness
root@nitrogen6x:/ # echo 0 > /sys/class/backlight/pwm-backlight.2/brightness
(N.B. PWM4 maps to pwm-backlight.3 and PWM3 to pwm-backlight.2 because hardware folks start numbering at 1 for some unknown reason)
Dual-channel (bonded) LVDS
Dual-channel LVDS is much simpler, since it doesn’t involve multiple backlights, but it does have some quirks because:
- U-Boot doesn’t yet support it, and
- We don’t have an off-the-shelf panel to auto-configure
We tested against a 22-inch 1080p display and added support for it to our boot script. You can configure for this resolution by setting the panel variable in U-Boot in the same manner as used for our 1280×800 displays:
U-Boot > setenv panel 1080P U-Boot > saveenv && reset
We are looking for an HD panel to offer as a companion product. Please let us know what type/size of panel you’d like to see.
4 GiB quirks
Now for the fine print.
There appear to be some bugs in the GPU acceleration when operating with more than 2GiB of RAM. As discussed in this post on i.MX Community site, we saw some very odd behavior with multiple displays when porting our Nitrogen6 Max kernel to Android.
The problems went away if we either set the max memory to 2GiB using the mem=2G kernel command-line argument or if we disabled hardware overlays in the Developer Settings panel.
When enabled, the Hardware Overlays feature allows applications to write directly to GPU surfaces, which minimizes the number of copies needed when updating graphic elements. This is speculation, but we believe that some piece of the graphics stack is seeing physical addresses > 2GiB as being invalid in a similar way these gstreamer components. The gstreamer components were using virtual addresses, but we believe the issue to be related.
Unfortunately, the setting in Developer Options is not persistent, and the problem components are closed-source, so we’ll have to defer to Freescale for a fix.
Fortunately, this is relatively easy to work around, and in this image, we’ve renamed the file /system/lib/hw/hwcomposer_viv.imx6.so to /system/lib/hw/hwcomposer_viv.imx6.so.disabled, which prevents the use of hardware overlays and doesn’t seem to have a dramatic impact on performance.
If you’re using this image on a BD-SL-i.MX6 or Nitrogen6x, you’ll want to put this file back:
root@nitrogen6x:/ # mount -o remount,rw /system root@nitrogen6x:/ # mv /system/lib/hw/hwcomposer_viv.imx6.so.disabled /system/lib/hw/hwcomposer_viv.imx6.so root@nitrogen6x:/ # sync && reboot