Put a Raspberry Pi CM4 into an original iPad

Open up a 2010 iPad, remove its logic board, and fabricate a new board based around the Raspberry Pi CM4.

Public Chat
Similar projects worth following
The 2010 iPad is completely unsupported, and is almost useless. It will still run old apps, but almost all internet-connected apps are broken. Even browsing the web in Safari is difficult, since iOS 5 has out-of-date TLS CAs.

But still, it's a pretty good piece of hardware in many ways. If we were to replace the logic board, we could still use these parts:

* Case
* 25 watt-hour battery
* capacitive touchscreen digitizer
* 1024x768 LCD
* 2x wifi/bluetooth antennas
* mono speaker
* TRRS port
* microphone
* ambient light sensor
* four buttons (lock/unlock, volume up, volume down), one switch (rotation)
* The wifi/BT module
* 30-pin connector

In this project, I am building a replacement logic board around a Raspberry Pi CM4.

Apple sold millions of iPads the year they were introduced. These devices were capable of browsing the web, watching movies, and playing games, with up to 10 hours of battery life and an intuitive touchscreen display. Apple essentially defined what a tablet should look like, and competitors are still playing catch-up.

However, all the original iPads are many years out of date. While some apps still work, and some can be made to work by jailbreaking the device, due to a lack of software support by Apple, these tablets are unable to do many of the things they used to be capable of.

The hardware isn't terrible, though! The iPad has a nice touchscreen, an okay LCD, a beefy battery, and enough buttons and ports to make it still useful as a computing device.

With this project, I intend to make a logic board for the original iPad based around the Raspberry Pi CM4 or another similar SoM. This will allow people to upcycle their obsolete iPads into fully-functioning tablets, which should be able to run Linux and Android.

Hopefully by giving these venerable devices a new lease on life, we can keep some of them out of landfills.

  • Some progress on the LCD

    Evan07/04/2022 at 06:24 4 comments

    The iPad's LCD wants its video input data in the LVDS format, but the CM4 can't output LVDS. It can, however, output DSI video, and there are chips like the sn65dsi83-q1 from TI which can convert from DSI to LVDS.

    About a year ago, I had gotten the sn65dsi83 somewhat working on the previous revision of my board. However, I ran into an issue with that board design that was difficult to work around: That board was designed to work as a hat for a full-size Pi (for ease of controlling which parts of the board were connected), so it only supported the 2 lanes of DSI that are exposed on the 15-pin display FFC on the Pi 4. This made it impossible to get clock speeds in the right ranges to make everything happy:

    The LCD panel from the iPad wants an LVDS clock between 97MHz and 103MHz. The sn65dsi83 driver calculates a DSI clock speed for for a desired LVDS clock frequency based on the pixel rates required and how many lanes of DSI you're using. (In this case, it wanted a 600MHz clock, which the sn65 would then divide by 6 to get 100MHz.) The Pi's DSI driver, vc4_dsi, then rounds this requested DSI clock speed up to the nearest integer division of 1.5GHz. In the case of 2 DSI lanes, this meant the Pi was trying to send a 750MHz DSI clock, and divide by 6 to get a 125MHz LVDS clock. These clock speeds are out of spec for both the sn65 (which only supports up to 500MHz DSI clocks) and the panel (which wants 100MHz clocks).

    The fix would be to use 4 lanes of DSI -- with 4 lanes, the sn65dsi83 driver would request a 300MHz clock (which the vc4_dsi driver would happily provide, as that's one fifth of 1500 MHz), which the sn65 would then divide by 3 to get the 100MHz LVDS clock. I set aside any further work on the sn65 until I had my second board revision.

    Picking up where I left off

    Now that I've got my CM4-based board (which has all 4 lanes of DSI routed), it was time to try getting video working again.

    One of the first things I did was to skim through the updates on this massive thread on the Raspberry Pi forums, which is the de facto place to discuss using the sn65dsi83 with the Raspberry Pi. So, so many updates.

    An engineer from the Raspberry Pi foundation, who goes by 6by9 on the forums, maintains a branch of the Linux kernel with patches to the sn65dsi83 driver. I pulled the latest version of their branch and merged it with the changes from my branch from last year. I double-checked the settings in the device tree overlay file (updating e.g. which GPIO pins are connected to the enable pin on the sn65 and its voltage regulator).

    Before trying it out, I looked at the area of my board near the sn65 to check for short circuits and such. (This is my last copy of the chip, and they're only available from a few places, which are selling at quite a bit above MSRP.)

    Satisfied that I wasn't going to fry the chip, I enabled the dtoverlay. I was greeted with this error message on boot:

    [   18.154108] sn65dsi83 10-002d: failed to attach dsi to host: -517

    I used some tricks I've learned during this project to get more information out of the kernel at boot: specifically, adding a bunch of dyndbg flags to the kernel command line in /boot/cmdline.txt:

    ti_sn65dsi83.dyndbg="+pmf" vc4.dyndbg="+pmf" panel_simple.dyndbg="+pmf" drm_kms_helper.dyndbg="+pmf" component.dyndbg="+pmf" 

    (This enables debug messages in the ti_sn65dsi83, vc4, panel_simple, ... kernel modules.)

    After adding some more debug messages to those modules, I ended up with this in my boot log:

    [   17.888125] calling  sn65dsi83_driver_init+0x0/0x1000 [ti_sn65dsi83] @ 366
    [   17.900948] sn65dsi83 10-002d: supply vcc not found, using dummy regulator
    [   17.902829] systemd-journald[136]: Successfully sent stream file descriptor to service manager.
    [   17.907747] systemd-journald[136]: Successfully sent stream file descriptor to service manager.
    [   17.918315] systemd-journald[136]: Successfully sent stream file descriptor to service manager.
    [ 17.942603] systemd-journald[136]:...
    Read more »

  • Getting the GT9110 touchscreen controller working

    Evan07/04/2022 at 02:49 2 comments

    I've been testing out the GT9110 for the past few days, and finally got it working today.

    My board uses a Goodix GT9110 touchscreen controller, which is closely related to a few other parts (GT911, GT928, etc.), and is basically the only touchscreen controller that I could find which met my requirements:

    1. Has enough drive and sense pins to work with my touchscreen
    2. A reasonable footprint which doesn't require expensive, high-density PCBs (which excludes the mXT2952, an 0.5mm-pitch BGA)
    3. Available in small quantities for a reasonable price (which excludes the MXT2912TD-A)
    4. Actual datasheets are available (which excludes a bunch of Cypress chips)
    5. Linux drivers are available

    (I should note that I haven't found an English datasheet for the GT9110, only one in Chinese. However, I did find English datasheets for related chips, like the GT911 and GT9113. These, plus Google Translate, were enough to lay out my PCB.) 

    On my previous iteration of the board, the i2c communication to the GT9110 was unreliable -- it wouldn't respond on i2c until a little while after the INT pin went high, which made the Linux goodix driver unhappy. I had guessed that might've been because the bodge I had to do for the INT pin wasn't making a good connection.

    Initial progress

    I dug up the device tree overlay file I had written for testing, and updated the GPIO numbers to match my new board revision.

    Fortunately, the new board doesn't have the same communications issues from the old board -- the Linux driver was able to talk to the GT9110 successfully, and create a file under /dev/input/event*.

    Getting stuck

    However, beyond initializing the driver, nothing else would happen. The INT pin would go high during driver initialization, and wouldn't change when I touched the screen. No further i2c communication was happening. Looking at the drive pins with an oscilloscope, I could see nothing was happening.

    An error immediately stood out to me:

    [   67.112771] Goodix-TS 1-005d: Direct firmware load for goodix_9110_cfg.bin failed with error -2

    I searched the web for a goodix_9110_cfg.bin, but couldn't find any example files. I did, however, find a few relevant threads:

    Nobody seems to mention needing a goodix_9110_cfg.bin (or goodix_911_cfg.bin, goodix_928_cfg.bin, or whatever); everybody managed to get their touchscreens working after a while by fixing basic issues with their device tree overlay files.

    Thinking I might have the wrong settings for my interrupt pin, I tried various combinations of pull-up/down/hi-Z, interrupt configuration (IRQ_TYPE_EDGE_FALLING, IRQ_TYPE_EDGE_RISING, IRQ_TYPE_LEVEL_HIGH, IRQ_TYPE_LEVEL_LOW). None of these seemed to help - several of those combinations prevented i2c communications entirely.

    Eventually, I gave up on that and focused on the firmware load error again. Adding a bunch of debug printfs to the driver and watching i2c communication with my logic analyzer (I'm using the Logic 8 from Saleae), I could see that it was:

    • Identifying the GT9110 on i2c
    • Trying to load the firmware from disk, and complaining that it isn't there. (The internet tells me it's looking in /lib/firmware, among other places)
    • Reading a bunch of data from the GT9110 starting at register 0x8047, which is the beginning of the configuration registers.
    • Leaving the INT pin high, never signalling that it had data.
    My board with the logic analyzer hooked up. I neglected to put proper test points on the board, so instead I've just gotten into the habit of scraping some solder mask off with a scalpel and soldering a bit of enameled wire to a trace to give me something to hook a probe to. The bit of cereal box is there to prevent any accidental short-circuits between the back of my board and the metal on the screen.
    Zoomed-out view of driver...
    Read more »

  • Real-time clock: It's nice when something is easy.

    Evan06/29/2022 at 07:18 0 comments

    At the very last minute before ordering my PCBs, I realized I probably wanted a real-time clock on the board somewhere. I searched on Digi-Key, found the RV-8263-C7, which was:

    • in stock (not anymore, lol)
    • cheap
    • tiny
    • requires minimal external components (just a decoupling cap and a pull-up resistor on an output enable pin)
    • has a Linux kernel driver (this chip has the same protocol as the PCF85063)

    I found an empty spot on my board with I2C and VBAT lines nearby, and laid it out in a few minutes.

    Tonight, I decided to see if it was working:

    Throw together a quick dtoverlay file:

    / {
        compatible = "brcm,bcm2835";
        fragment@0 {
            target = <&i2c1>;
            __overlay__ {
                #address-cells = <1>;
                #size-cells = <0>;
                status = "okay";
                rv8263: rtc@51 {
                    compatible = "microcrystal,rv8263";
                    reg = <0x51>;
                    // quartz-load-femtofarads = <12500>;

    (This is basically just device tree overlay boilerplate plus the example from the documentation.)

    Compile with make -j4 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs, copy the output dtbo file to the CM4's /boot/overlays directory, and run dtoverlay pipad-rtc.dtbo to load the overlay. Test with sudo hwclock --systohc then sudo hwclock --get. Add dtoverlay=pipad-rtc to /boot/config.txt, reboot, check sudo hwclock --get again, and it's still working.

    Remove the fake-hwclock package and disable the systemd unit with the instructions on, and double-check that it's actually reading the hardware clock on startup (and not just using NTP) by using rfkill block wifi to turn off wifi, reboot, and check that the time is accurate.

    No incorrect PCB footprints or unwired pins, no Linux kernel debugging. Just things working correctly on the first try. Feels good.

  • Figuring out why the CM4 wouldn't boot when attached to my board

    Evan06/26/2022 at 08:27 1 comment

    In my previous log entry, I had fried my CM4 by shorting 5V to 3.3V, so I had to order a replacement, which arrived last week.

    The next thing for me to test is whether I can boot the CM4 on my board, so I installed Raspberry Pi OS and set enable_uart=1 in /boot/config.txt. With the CM4 still in the CM4IO, I verified that I could see boot messages and log into the CM4 over serial.

    I bodged some wires onto the UART traces on my board and connected them to my USB-serial adapter. I moved the CM4 off the CM4IO and onto my own board, and booted it, and.... nothing. Zero output from the UART.

    I figured it must be crashing somewhere during the bootloader or early kernel boot settings, so I moved the CM4 back to the CM4IO and:

    1. added console=ttyS0,115200n8 loglevel=7 earlycon=uart8250,mmio32,0xfe215040 to my /boot/cmdline.txt, to get early kernel messages.
    2. set BOOT_UART=1 in boot.conf to get output from the bootloader.

    Still nothing...

    After a while, I figured out that the TX pin on my 100-pin connector wasn't properly soldered to my board. Of all the pins to have issues, it had to be that pin!

    At this point, it still isn't booting, but I can at least see kernel messages. I would get a warning at some point during boot:

    [    3.178888] ------------[ cut here ]------------
    [    3.183639] Firmware transaction timeout
    [    3.183693] WARNING: CPU: 2 PID: 1 at drivers/firmware/raspberrypi.c:67 rpi_firmware_property_list+0x1dc/0x250
    [    3.197794] Modules linked in:
    [    3.200888] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 5.15.32-v8+ #1538
    [    3.207583] Hardware name: Raspberry Pi Compute Module 4 Rev 1.1 (DT)
    [    3.214098] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
    [    3.221144] pc : rpi_firmware_property_list+0x1dc/0x250
    [    3.226432] lr : rpi_firmware_property_list+0x1dc/0x250
    [    3.231719] sp : ffffffc00960b9b0
    [    3.235068] x29: ffffffc00960b9b0 x28: 0000000000000000 x27: 0000000000000004
    [    3.242300] x26: ffffffc009a5d008 x25: ffffff8002aa8b80 x24: 0000000000001000
    [    3.249530] x23: 0000000000000014 x22: ffffffc008e8a9c8 x21: ffffff80020b7200
    [    3.256758] x20: ffffffc009a5d000 x19: ffffffc009491158 x18: 0000000000000010
    [    3.263986] x17: 0000000000000001 x16: 0000000000000019 x15: 0720072007200720
    [    3.271214] x14: 0720072d072d072d x13: 74756f656d697420 x12: ffffffc0093a6670
    [    3.278442] x11: 0000000000000003 x10: ffffffc00938e630 x9 : ffffffc0080ec768
    [    3.285670] x8 : 0000000000017fe8 x7 : c0000000ffffefff x6 : 0000000000000001
    [    3.292899] x5 : 0000000000057fa8 x4 : 0000000000000000 x3 : 0000000000000001
    [    3.300126] x2 : 0000000000000000 x1 : 529515f3f0203b00 x0 : 0000000000000000
    [    3.307354] Call trace:
    [    3.309824]  rpi_firmware_property_list+0x1dc/0x250
    [    3.314760]  rpi_firmware_property+0x78/0x110
    [    3.319169]  rpi_domain_on+0x6c/0x90
    [    3.322789]  genpd_power_on.part.23+0x188/0x220
    [    3.327375]  __genpd_dev_pm_attach+0x104/0x238
    [    3.331870]  genpd_dev_pm_attach+0x6c/0x88
    [    3.336014]  dev_pm_domain_attach+0x28/0x40
    [    3.340249]  platform_probe+0x58/0xe0
    [    3.343957]  really_probe+0xc0/0x318
    [    3.347573]  __driver_probe_device+0x80/0xe8
    [    3.351892]  driver_probe_device+0x88/0x118
    [    3.356123]  __driver_attach+0x78/0x110
    [    3.360004]  bus_for_each_dev+0x7c/0xd0
    [    3.363890]  driver_attach+0x2c/0x38
    [    3.367505]  bus_add_driver+0x194/0x1f8
    [    3.371385]  driver_register+0x6c/0x128
    [    3.375265]  __platform_driver_register+0x30/0x40
    [    3.380026]  xhci_plat_init+0x38/0x44
    [    3.383737]  do_one_initcall+0x54/0x2a0
    [    3.387619]  kernel_init_freeable+0x250/0x2d8
    [    3.392031]  kernel_init+0x2c/0x130
    [    3.395564]  ret_from_fork+0x10/0x20
    [    3.399186] ---[ end trace b159b7c67bd50e8b ]---

    Then after a few more messages, it would hang.

    From what I can tell from this issue where people saw the same "Firmware transaction timeout" warning, this happens when the code running on the VC4 locks up.

    Getting more output

    The internet told me to add initcall_debug to my kernel command line to get more output on startup. This prints a message per kernel subsystem on boot....

    Read more »

  • CM4 carrier board: chip shortage pain, bodges, silly mistakes, and tragedy.

    Evan06/14/2022 at 07:56 0 comments

    Chip shortage problems

    Shortly after my last project log, I tried to place an order for all the new components that I'd need for the next revision of my board, as well as re-stocking anything that I had already used most of. I discovered that my backlight controller of choice had gone out of stock with indefinite lead times, so I had to swap to a different backlight driver. (I switched from the TPS61176 to the TPS61177, which was the next cheapest suitable controller on DigiKey.)

    I ordered my parts then modified my PCB design to accommodate the new chip.

    Fit Testing

    Once I had parts in hand, I made a mockup of my board by printing the front and back solder mask layers on separate sheets of paper, and then gluing them to either side of a piece of cardboard taken from a soda can box. (This stackup comes remarkably close to the 0.8mm thickness of my PCB.) With some double-sided tape, I affixed the connectors for the largest components -- the CM4 and the NVMe SSD -- snapped the CM4 and SSD in place, and did a fit test in my iPad case. The screen did not want to drop into place.

    I found a few things that I could change to improve the fit:

    1. I rotated the CM4 180 degrees, so that the BCM2711 processor (the thickest part of the CM4) is closer to the center of the case (where the iPad is thicker, so there's more room)
    2. I moved almost all of the other components from the front to the back of the board, in between the SSD and the CM4, leaving only the connectors (dock, ambient light sensor, touchscreen, buttons) and the touchscreen controller and audio codec. (The touchscreen and audio bits are on the other end of the board, and I didn't seem to have any trouble fitting that end.) This meant the battery charger, 3.3v buck-boost (for the SSD), 5V boost (for the CM4), the DSI-LVDS converter, and the backlight driver all moved to the back.

    I also needed to adjust the edge of the board to leave a spot where the LVDS cable can come up from the back of the case to the front of the board.

    All these changes required re-routing a significant chunk of the board, which took me a few weeks.

    Touchscreen controller testing

    Meanwhile, I decided to test the GT9113/GT9110 touchscreen controller on the previous iteration of my board. I had messed up the orientation of the FFC connectors for the touchscreen on that revision, but I figured I should at least test whether I can get the Linux kernel to talk to it. I'm glad I did -- I discovered a few things that were wrong with my PCB.

    The GT9110 touchscreen controller, with the hack I had to implement to get access to the INT pin.

    First of all, the Linux kernel driver wants the INT pin from the controller to be wired to a GPIO pin. I hadn't connected that pin anywhere, and  didn't leave myself any extra space on the pad to solder a wire to. I tried several things to bodge a connection to this wire before finding something that worked:

    • poking an enameled wire at the edge of the chip and trying to get it to solder in place: the pins on the chip are visible on the side, but even my finest soldering iron tip is enormous compared to the 0.4mm between adjacent pins.
    • removing the IC, soldering a 40AWG wire to the pad, and soldering the IC back down. It turns out, even  40ga wire is thick enough to keep the rest of the pads from reliably making contact when soldering. I still feel like I could've gotten this to work by adding more solder, but it was just too finicky, so I got frustrated and tried another approach:
    • (what ultimately ended up working, mostly?) I took a standard 0.1" header pin, and used a file on 3 sides to sharpen it to a point that's flush with the 4th side. I then glued this in place with some UV-cure solder mask, which is my new favorite thing for bodges. Assuming you use a thin layer, it cures in like 10 seconds under the provided UV flashlight. This is what's shown in the photo above.

    Another thing that I discovered was that...

    Read more »

  • RPi CM4 and Radxa CM3 versions of the board

    Evan01/26/2022 at 07:53 2 comments

    Since the last time I had a board made, I've discovered several revisions that I needed to make:

    - The 5V boost of the bq25895 cuts out long enough to shut off the Pi when you connect USB power.

    - I needed extra lanes of DSI going from the CM4 to the SN65DSI83 chip in order for all the clock rates to fall within the ranges allowed by the SN65 and the iPad's display.

    - The footprints for my touchscreen FFCs were backwards

    I took this opportunity to design a version of the board where I actually used the CM4 instead of having separate 40-pin connector / FFC for DSI / USB port on the board. I threw an M.2 slot on there for NVMe support, as well.

    The CM4-based version of my board.

    When I was nearly finished with that design, I learned about the Radxa CM3, which is the same form factor as the Raspberry Pi CM4 but has a third board-to-board connector providing several features that would be quite convenient for this application:

    • Audio codec with headphone out, mono speaker out, and microphone in
    • Battery charger
    • Power button handling
    • Native LVDS support on the DSI0 pins (and the extra DSI0 pins are broken out)
    • HDMI pins can also output DisplayPort (the dock connector on the iPad can speak DisplayPort, which is used to drive the 30-pin to HDMI adapter.)

    In addition, the Rockchip RK3566 that the Radxa CM3 is built around actually seems to have the ability to sleep, which is especially important on a tablet. On the CM4, I'll have to suspend to disk or just shut down or something.

    I think if I the Radxa CM3 had existed when I started this project, I might've chosen it over the Pi CM4, as it should require a lot less glue circuitry to make it work in this application. (I had originally considered the Pine64 SOPine and the Nvidia Jetson Nano, but I think I excluded these because the SO-DIMM connectors that they require wouldn't fit between the case and the screen.) As a bonus, the RK3566 is less tall than the BCM2711, which may buy me a little vertical room, depending on the other components on the CM3.

    I've also designed a version of my board based around the Radxa CM3. Once I figured out the position and orientation of the third connector on the CM3, this wasn't too bad -- it has far fewer components than the CM4 version of the board. It's essentially just connectors, the touchscreen controller, a buck-boost converter for the NVMe slot, and some audio switches.

    Radxa CM3-based version of my board

    Since the Radxa CM3 / RK3566 clearly has less software support than the Pi (I think as of the time of writing, you can't even get HDMI output, let alone LVDS.), I'm planning to hedge my bets and have both boards made.

  • Colors! (sn65dsi83 test pattern)

    Evan08/23/2021 at 06:26 0 comments

    Thanks to the help of some folks on the Raspberry Pi forums, I've got the sn65dsi83 driver loading, and the Pi generating enough DSI signal for the SN65DSI83 to be able to generate a test pattern (it uses the DSI clock to generate the LVDS clock)

    Hopefully I can get those black lines to go away.

  • Using ftrace to debug device tree problems

    Evan08/18/2021 at 07:28 0 comments

    For the past few days, I've been trying to get the sn65ds83 driver (recently added to linux) running and talking to my board. It has been a (re-)learning experience trying to get this device tree overlay to cooperate.

    Following my own advice from the last time I touched device trees, I used udevadm monitor and dmesg -w to watch for kernel/udev messages while loading my overlay with sudo dtoverlay pipad_screen. This gave me this helpful error message:

    [  178.309859] sn65dsi83: probe of 1-002d failed with error -2

    From what I can tell from looking at the kernel source, this implies that the sn65dsi83_probe function was returning -2. Unfortunately, the sn65dsi83_probe function can return errors from several different places. Fortunately, there's a kernel feature called ftrace that can trace every function call that happens within the kernel. The easiest way to use it is to use the trace-cmd command, which you can install on Raspberry Pi OS with apt install trace-cmd. You record with trace-cmd record -p function_graph (with various options for filtering), then view the results with trace-cmd report.

    Supposedly, you can trace everything by just running trace-cmd record -p function_graph with no filter options, but when I tried this, I had a lot of dropped events and didn't see the sn65dsi83_probe function in the results.

    After learning some things about ftrace (by manually constructing a list of functions to filter on with the -l flag), I discovered that ftrace can only trace functions in kernel modules that are loaded before ftrace starts. Normally, the ti-sn65dsi83 module is loaded automatically when I run dtoverlay pipad_screen, but that prevents ftrace from seeing it.

    If I manually modprobe ti-sn65dsi83 before running trace-cmd record -p function_graph -F dtoverlay pipad_screen, I get no dropped events, and the trace for the sn65dsi83_probe function was there in the output of trace-cmd report:

    sn65dsi83_probe() {
      devm_kmalloc() {
        __kmalloc_track_caller() {
        devres_add() {
          _raw_spin_lock_irqsave() {
          _raw_spin_unlock_irqrestore() {
      of_device_get_match_data() {
        of_match_node() {
          _raw_spin_lock_irqsave() {
          __of_match_node.part.0() {
            __of_device_is_compatible() {
            __of_device_is_compatible() {
          _raw_spin_unlock_irqrestore() {
      devm_gpiod_get() {

    This implies that sn65dsi83_probe was returning immediately after the call to devm_gpiod_get finished. Oh, right, I never put the enable GPIO pin for the sn65dsi83 in my dts file. I figured the property would be called enable because that's the string being passed to devm_gpiod_get, but nope. From looking at documentation for other bridges, I inferred that it's enable-gpios.

    Adding enable-gpios = <&gpio 5 0>; to my device tree and trying again, this time I get from dmesg -w:

    [   95.093834] sn65dsi83: probe of 1-002d failed with error -22

     Looking at my report, this time I see:

    sn65dsi83_probe() {
      devm_kmalloc() {
      of_device_get_match_data() {
      devm_gpiod_get() {
      of_graph_get_endpoint_by_regs() {
      of_property_count_elems_of_size() {
      of_graph_get_remote_port_parent() {

    Looks like it's failing just after of_graph_get_remote_port_parent and of_node_put. These aren't called directly from sn65dsi83_probe, but by sn65dsi83_parse_dt. Because sn65dsi83_parse_dt is defined as a static function, it can't be traced by ftrace, and everything it calls appears directly beneath sn65dsi83_probe.

    I think I'm being caught by this code:

        ctx->dsi_lanes = of_property_count_u32_elems(endpoint, "data-lanes");
        ctx->host_node = of_graph_get_remote_port_parent(endpoint);
        if (ctx->dsi_lanes...
    Read more »

  • First light: testing and fixing the backlight controller

    Evan07/10/2021 at 05:07 0 comments

    Based on my guess of how complicated testing the different components will be, I decided to test the LCD backlight controller next. 

    For this part of my PCB, I basically built the example circuit from the datasheet of the TPS61176. This chip is essentially a DC-DC boost converter and 6 constant-current/PWM sinks. You control it by providing a PWM signal on its PWM/EN input. It decodes this signal and then runs its own PWM on each IFB# pin.

    Not wanting to risk frying my iPad's display, I wanted to first test with my own string of LEDs. However, I'm a dummy and I neglected to put any test points on this part of my PCB, and because both ends of the trace end up at fine-pitch footprints, I opted to scrape away some solder mask and solder some magnet wire directly to some traces.

    Magnet wire soldered directly to traces. Don't forget to add test points to your PCB!

    I dead-bug soldered a few LEDs together to make my test string, and connected them to the common anode and one of the cathode lines, which works great:

    fading the brightness from 0% to 100%

    The TPS61176 will increase the anode voltage until your LEDs start actually drawing current, so it basically supports strings of LEDs with arbitrary forward voltage, within its voltage range.

    After double-checking that I hadn't flipped the pinout for the display, I decided to connect the actual LCD panel. Powered it up and ....nothing. Black. The anode voltage was 3.6V (so, not boosted at all). My hypothesis is that it's detecting an open circuit on all the LED strings, so it disabled the boost converter. Some basic testing confirms:

    The anode voltage jumps (higher than my Saleae Logic 8 can measure), and then falls back down. I wonder how high that voltage is going? Is it higher than the 18V required to drive the backlight on the LTN097XL01-A01 panel in my iPad?

    I soldered a few more wires onto my board: one at the MODE/FAULT pin, and one at the OVP pin (which is connected to a voltage divider with 143k / 1M, which divides the anode voltage by 8). Rerunning the test gives me:

    1.5V at the OVP pin. There's my problem! Turns out the reference voltage for the OVP pin is 1.5V, and with the 1/8 division, I'm only getting 12V max. I need to adjust the ratio on my voltage divider.

    After swapping the 143k resistor for an 82k resistor, the backlight works! 

    the backlight on my LTN097XL01-A01 glowing

  • Power supply testing, part 2

    Evan07/08/2021 at 06:05 1 comment

    I assembled the front of my board yesterday (dealing with 0402 components is tedious. I really should just pay JLCPCB to solder on most of the passives for me.) Today, I wanted to quickly test the power supply to make sure I hadn't broken anything yesterday.

    I attached a battery (I managed to find another LiPo battery buried in a drawer), checked output voltage (5.1V ☑️), wired up the raspberry pi (which booted.) Everything seems to work as well as it did two days ago. However, I tested a few things that I hadn't tested before, and discovered a few unfortunate things:

    When I plugged in the USB charge cable, the red LED on the Raspberry Pi shut off. However, the Pi didn't actually shut down - I think the input voltage dropped just enough that the Pi turned off the LED. (The USB charger I'm testing with only puts out about 4.5V.)

    However, when I unplugged the USB cable, the Pi did actually shut off. Turns out, it takes about 38ms for the bq25895 to start the boost converter after VBUS drops to 0, so my 5V output drops to about 0.2V below Vbat, so about 3.6V in this case. (probably being fed entirely through the external Schottky diode.)

    Screenshot of Logic 2 showing the voltage drop on the 5V output when you unplug the USB input cable.

    From this trace of the various voltage rails, we can see that PMID (the 5v output of the bq25895) and 5V @ pi (the pi's 5v rail, connected by wire to PMID - I just wanted to make sure there wasn't too much voltage drop on the wire) drop down to about 3.6V. This is low enough that the Pi shuts down its 3.3V rail.

    Because of this issue and the risk of USB voltage being passed directly to the Pi if the bq25895 negotiates a higher voltage, I think I'm going to have to add a separate boost converter like the SuperPower-RPi project does. (I based my bq25895 schematic heavily off of theirs.)

    Thanks a ton to Seth K from the SuperPower discord for his input on this.

View all 18 project logs

Enjoy this project?



Hassla wrote 06/29/2022 at 13:47 point

Really nice your frequent updates currently.

  Are you sure? yes | no

Tom Cubie wrote 06/28/2022 at 02:43 point

This is Tom from Radxa, this project is very interesting and we can help to troubleshooting hardware issues and get everything working. You can join our discord

"Since the Radxa CM3 / RK3566 clearly has less software support than the Pi (I think as of the time of writing, you can't even get HDMI output, let alone LVDS"

I think this is the mainline kernel status, for the Rockchip 4.19 vendor kernel, we have everything working already.

  Are you sure? yes | no

Michael Shaub wrote 06/28/2022 at 00:27 point

this is awesome! Are you planning to make parts available on Tindie? I’ve been wondering why I kept my original iPad. Now I know!

  Are you sure? yes | no

Evan wrote 06/29/2022 at 18:42 point

Maybe! A lot of the parts are getting hard to find, and I dunno if I want to provide customer support 😆

  Are you sure? yes | no

jimmyplaysdrums wrote 06/27/2022 at 23:39 point

Very cool. Looking forward to seeing more!

  Are you sure? yes | no

Hassla wrote 06/20/2022 at 22:59 point

Awesome work, keep up the good work!

Hopefully you can revive your CM4.

  Are you sure? yes | no

Evan wrote 06/21/2022 at 19:21 point

Thanks for the words of encouragement! My replacement CM4 came in, and I'm working on getting it booting. Hopefully will have another project log soon. I bought the replacement PMIC chip from AliExpress, so it'll take a month or two to arrive.

  Are you sure? yes | no

Hassla wrote 01/26/2022 at 11:40 point


An absolute beauty of a board, hopefully all works as intended.

  Are you sure? yes | no

iamcanarin wrote 11/16/2021 at 15:15 point

This looks like a good solution for UPS :

  Are you sure? yes | no

iamcanarin wrote 11/08/2021 at 11:09 point

Hi, just want to say how awesome work you did so far. I also had an idea to fit Raspberry Pi into the old iPad. I was wondering since speakers are "dumb",  wouldn't it be enough to let us say use something like  PCM5101A from parts which are already tested to run iPad speakers, or am I missing something?

  Are you sure? yes | no

Evan wrote 11/10/2021 at 19:28 point

Yeah, that looks like it should work. Seems like that's using the PCM5101A codec + the [APA206](, which looks like a speaker amplifier. If I have trouble solving my [audio quality problem]( on the tlv320aic3206, I'll look around at different codecs. The PCM5102A seems to be the same part as the PCM5101A but with better audio quality specs.

One reason I went with the tlv320aic3206 is that it can drive 16 ohm headphones directly, whereas the PCM510x specifies a minimum load of 1kOhm on its LOL/LOR, so it may require an additional headphone driver circuit.

  Are you sure? yes | no

Hassla wrote 11/16/2021 at 18:52 point

The TLV320AIC3206 is really interesting, I wanted to use the PCM5100, TPA6133A2 and PCM1863, to subsides the CS4206 or the succesor CS4207, but these are not I2S. So the TLV320AIC3206 could probably used for my application with 2 or 3 Speaker and a Headphone out and input.

  Are you sure? yes | no

Hassla wrote 09/24/2021 at 15:50 point

Did you proceeed with working on this project? Or did you set it aside.

I have currently set it aside in favor of other projects, because the main chips, like the CM4 itself or the SN65DSI85, are simply not available. And of course during the design I fell down the rabbit hole with USBC and the thousand possibillity with DP/HDMI over USBC etc..


  Are you sure? yes | no

Evan wrote 09/24/2021 at 18:49 point

Yep, I'm still working on it. I picked up a few sn65dsi83's while they were still in stock, and have been trying to get it working since. Hopefully I don't destroy any of them.

I'm going to have at least one more board revision (to switch from my 40-pin prototyping layout to the CM4 connectors, and to fix some issues I've found), but so far the only new parts I'm going to need are passives, connectors, and a SMPS chip which seems to still be in stock.

You might try picking up a later iPad screen - I think they switched to eDP when they went to the retina screens, and it looks like the SN65DSI86IPAPRQ1 (MIPI to eDP) is still in stock at TI / Mouser / Arrow. I briefly looked into this because I was curious if I could upgrade this to a retina display. I think the later screens are a bit shorter in one dimension and a bit longer in another, but it might be possible to modify the mounting hardware to make it fit.

EDIT: oh right, you said you're hacking a Macbook. Maybe you want to use the RTD2660H if you can't find any other MIPI-LVDS bridge ICs?

  Are you sure? yes | no

Hassla wrote 09/26/2021 at 18:02 point

That's nice to hear!

Yeah the RTD2660H was my first Idea, like Joel Hill , used in his attempt to use a macbook and a RPi together.

Die SN65DSI85 was my first Idea, since it was already paired with the RPi from some guys in the RPi Forum. But I am going to look out for another MIPI to Dual LVDS.

But since i cant even get a CM4, I suppose i just wait for the World of Chips become normal again.

  Are you sure? yes | no

Evan wrote 12/01/2021 at 19:35 point

If you're not glued to the CM4, you might look at the recently released SOQuartz from Pine64[1] and the Radxa Rock3 CM3[2]. Both are based around the RK3566, are pin-compatible with the CM4, and can supposedly output LVDS signaling on the MIPI-DSI pins. The Radxa board has an extra 100-pin connector which breaks out some more IO. It's got USB3, HDMI, and eDP, so it might be perfect for messing around with USB C alternate modes.

The SOQuartz seems to be available on the Pine store, but I can't find the Radxa CM3 anywhere in stock. I'm going to pick up an SOQuartz and see how it goes.


  Are you sure? yes | no

Hassla wrote 12/02/2021 at 20:59 point

Yeah both of the alternative CMs are interesting, especially with LVDS and USB3 & SATA straight out of the box. Since the prject dont have any timelimit, I probably stick with the RPi. But I am still looking in the other two. oThanks for that.

  Are you sure? yes | no

Evan wrote 12/13/2021 at 06:49 point

I think the SOQuartz only breaks out 2 lanes of the combo LVDS/MIPI-DSI transmitter to the cm4 pins: page 15, top left. They break out all 4 lanes of the other MIPI-DSI transmitter, but that doesn't support LVDS according to the rk3566 datasheet.

I assume Pine64 did this to be as similar as possible to the CM4, which only has 2 lanes on DSI0, and 4 lanes on DSI1.

  Are you sure? yes | no

Evan wrote 12/13/2021 at 08:24 point

The Radxa CM3 has the remaining two lanes of LVDS broken out to the third board to board connector, and the wifi/2GB/16GB model is in stock at

I guess that may still not be enough for your display if you need dual LVDS.

  Are you sure? yes | no

Hassla wrote 08/22/2021 at 16:45 point

Just a comment to appreciate your project. I like it very much, since I am in the progress of trying to hack a Macbook A1286 i really enjoy your work. Keep it up!

  Are you sure? yes | no

Evan wrote 08/23/2021 at 06:24 point

Thanks! I bet there's a lot of similarity internally -- I think the iFixit teardowns of the iPad mentioned they used some similar parts in the iPad as on the contemporary Macbooks.

If you start writing up your project somewhere, let me know!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates