I recently picked up a new AYN Odin gaming handheld, and ended up working on support for it in the Linux kernel. I thought the process and things I learned during it would make for some good blog posts, so part of the way through the process I started writing down what I was doing, in the hope it would be interesting to others when published. This post will be the first in a series hopefully following the journey in getting full, or at least workable, support for it in upstream Linux so that anyone can install Linux on their Odin device and keep it up to date with the latest emulators, graphics drivers and so on.
The AYN Odin is actually a series of handheld gaming devices based on the same hardware platforms used in some Android smart phones. They seem to be aimed at emulating retro games and are powerful enough to emulate sixth generation game consoles such as the Nintendo GameCube. The Base and Pro models are built around the Qualcomm SDM845 system-on-chip, while the Lite model uses a Mediatek Dimensity 900. Out of the box they all run Android
TODO what version of Android
, however this is already almost 4 years old, Android 13 is the latest version nowadays and I wanted to upgrade the OS on the device to a modern version. Unfortunately I found that with Android devices, with the level of customisation each manufacturer does to the OS, the owner is at the mercy of the device manufacturer to forward-port those modifications to newer Android versions and provide updates, and there’s no sign of updates from AYN to support newer Android versions.
However, in theory the devices aren’t bound to Android forever - ultimately they are built to run a form of Linux OS, and so I decided to try and add support for it to upstream Linux so that it can get updates for the future, and be as customisable on the software side as any general-purpose Linux device. There are plenty of emulators and launchers that will run on generic Linux, so moving away from Android shouldn’t lose any of the functionality I wanted to use.
I’ll be focusing on the model I own, the Odin Pro, as its SDM845 system-on-chip is already quite well supported in upstream Linux, including support for several smartphones and laptops based on this SoC. The Mediatek-based Lite model unfortunately would not have the same base of support upstream to start from, due to Mediatek generally not contributing support for their devices to the Linux open-source project. Having researched this before buying, I decided to stay away from the Mediatek-based model due to their reputation. The Base model, although I haven’t actually used it, seems fairly similar to the Pro with the same SoC, only differing in the amount of RAM and flash storage, so work on the Pro should also benefit the Base model.
The first task I decided to take on was to figure out what information I could gather about the device, particularly about where this device differed from other upstream-supported devices, and what parts might not be supported upstream. Typically these parts would be peripherals not integrated into the SoC but added by the device manufacturer, for example display panels, touchscreens, buttons and other input devices.
On modern ARM Linux systems that don’t use ACPI, the description of the hardware present in the system is provided to the kernel by a device tree data structure. This structure normally describes all hardware that can’t be auto-discovered at runtime - for example, PCIe cards can be probed and discovered at runtime by a standard process, but a memory-mapped peripheral that just resides at a certain address can’t be discovered automatically, and so needs to be described in the device tree.
So, to help understand the hardware layout of the device, it would be really useful to see the device tree that the Android install is using to describe the hardware. The device tree is normally supplied to the Android kernel by the boot loader when it starts the kernel, in the form of a DTB (device tree binary). From what I could gather from searching online, the location where the DTB was stored could differ between different Android versions. In theory, it should be possible to dump the DTB from a running Android system, but I actually started researching this while the Odin was in transit to me from China, so I had to use what sources I could find online without having physical access to the device yet.
Sources of information
AYN’s Android kernel
AYN has published sources of their Android kernel on Github. They have stripped all commit history from the repo for some reason, but we can see in the Makefile that this kernel is based on upstream Linux 4.9.218, so we can pull the v4.9.218 tag from the main Linux stable Git repository and compare the differences between the upstream stable kernel and AYN’s codebase to find all the code added either as part of Qualcomm’s Android drivers, or AYN’s customisations.
Reading this diff showed a large amount of added code that looked like drivers for various Qualcomm peripherals. To try and cut down on the noise and pick out modifications specific to the Odin, I found another repository to use as a base which seemed to already contain the Qualcomm drivers. It didn’t quite match the version of Linux published by AYN, but when used as a base it produced a smaller diff than comparing against upstream Linux 4.9.218.
Existing upstreaming work
I discovered there had already been some work on upstreaming support for this device in 2022, but it hadn’t made it into the upstream kernel and still consisted of patches against the kernel version 5.18.
TODO: link
At the time of writing, kernel 6.4 is the latest version, so any work would have to be based on the next kernel in development (that would become 6.5).
I found instructions on Github on how to dual boot Android and either Windows or Linux on the device. Interestingly, there seems to be (at least) two revisions of the SDM845-based Odin models, named M0 and M2. At this point it seems like the main difference between the revisions is the type of display panel used.
The odin_custom_boot_...
archive linked from that page, in particular, is interesting material. It contains scripts to repartition the storage on the Odin to allocate equal amounts of storage to an Android installation and a Linux partition. As part of this, it needs to write Android data to the newly re-created Android partitions, and so it contains an Android boot image for each revision of Odin (odin-loader-m0.img
and odin-loader-m2.img
) and a “sparse” image containing the system partition, again with one for each revision of Odin (system_odin_m0_147.img
and system_odin_m2_151.img
). Reading the scripts shows which images are flashed to which partitions.