Case Study — Embedded Linux · Kernel · Hardware
A bargain-bin Android tablet, a Linux port, and two patches accepted into the Realtek WiFi driver
A 2019 Denver tablet too slow to play music on Spotify, kept out of the bin because the board underneath the software was fine. By September 17, 2026 it ran Linux 7.3 and drives a lighting rig from its touchscreen. On the way, a WiFi failure that survived every hardware theory turned out to be one missing step in a driver power-up table, and the fix went upstream: two patches applied by the rtw88 maintainer at Realtek.
- C
- Linux kernel
- Device tree
- DRM/KMS
- Buildroot
- U-Boot
- i2c
- SDIO
- OpenGL ES
- ffmpeg
- Python
Why a finished tablet was worth the work
A 10.1" Denver TAQ-102 from the 2019 bargain bin: Rockchip RK3126C, four Cortex-A7 cores, 1 GB of RAM, Android 8.1 Go, no security updates since 2019. As a tablet it was finished. It was too slow to play music on Spotify, which is the sort of detail that decides whether something goes in a drawer or in the bin.
The premise was that the board had not earned that. A 1024x600 LVDS panel, a touch controller, a battery, a PMIC and a WiFi chip are a kiosk or a controller waiting for a system that fits in them, and almost none of the badness was in the silicon. The aim was never "reuse the hardware" — it was to beat what the vendor shipped on it.
One fact made the whole thing tractable, and it is worth checking before buying any cheap Android device you intend to repurpose: the USB descriptor answered what the box would not. Vendor ID 0x2207 is Fuzhou Rockchip, whatever the marketing name says, and this board has a Rockchip boot ROM recovery path. Before anything was written to the device, the eMMC was dumped whole — which is the step that later turned a mistake into an inconvenience.
The WiFi bug: knowing you are right is not the same as checking
With Linux on it, WiFi died after every reboot. The failure persisted across warm restarts and even some power-off attempts. The kernel said `failed to poll offset=0x6 mask=0x2 value=0x2`, then `mac power on failed`.
The hardware was never really in question: Android had driven the same chip on the same board for years, so the difference was software. I checked anyway. The pwrseq reset line, the Bluetooth enable line, the 32.768 kHz clock and every switchable PMIC rail were each toggled against the wedged chip, and none of them brought it back, while the vendor driver recovered it every time. That is what pointed at the driver rather than the board — and the elimination was worth doing precisely because I was already sure.
The defect was in a power-state transition table. On an RTL8723CS, `trans_carddis_to_cardemu_8703b` had a single entry, clearing the hardware power-down bit, where the near-identical `trans_carddis_to_cardemu_8723d` has seven. The SDIO suspend request on local register 0x86 was never withdrawn, so the reverse transition was never completed: the chip came back with the WLAN MAC unpowered while the SDIO function still enumerated happily. The system could see the WiFi chip; the part that does the WiFi had no power.
What went upstream, stated exactly
- Two patches sent to linux-wireless@vger.kernel.org and linux-kernel@vger.kernel.org, applied by Ping-Ke Shih, the rtw88 maintainer at Realtek, on 2026-09-16: "2 patch(es) applied to rtw-next branch of rtw.git, thanks". Both carry Acked-by: Ping-Ke Shih <pkshih@realtek.com>.
- 43f6347e8bbe — wifi: rtw88: 8703b: complete the card-disable to card-emulation transition.
- 73e3b1c94c7d — wifi: rtw88: 8703b: stop the PCIe DMA write reaching SDIO.
- The honest description is "applied to the maintainer tree", not "in the Linux kernel". rtw-next is the staging branch that feeds wireless-next; the September 16 record confirms acceptance into the maintainer tree, without claiming inclusion in a mainline release.
- The thread is public and checkable: lore.kernel.org/linux-wireless/178914109042.64584.1681714272474754544@cristiandeluxe.dev/ — including the part where the first send bounced three times before the series reached the lists.
The defect every instrument I had said was not there
For two days the picture carried what I could only describe as a small wave passing over things, like electric noise — on any content, on a completely static image. Every measurement said the panel was steady, because every measurement was of brightness, and the artifact was sideways displacement. A frame-difference motion meter reported "flat" throughout; the same meter once reported motion on a still scene, from its own auto-exposure.
What ranked the suspects was reading a four-band test pattern by eye: single-pixel vertical lines unwatchable, horizontal lines less so, flat grey slight, flat white nothing at all. With every data bit at one, a mis-sampled bit is still one — so the artifact scaled with how much the LVDS link toggled. That pattern suggested link timing rather than rendered content, so I investigated the transmitter.
The measurement that settled it: display single-pixel vertical lines from one dumb buffer with no page flips and no GPU, record with a motionless camera, and extract the horizontal phase of the pattern row by row through an FFT bin. Split the result into the panel's fixed geometric bend, about 1 px, which nobody ever notices, and the frame-to-frame movement, which is what the eye calls a wave. Three PHY PLL settings at 350 MHz measured 0.63 to 0.81 px rms of movement. The vendor's own dividers, 336 MHz at prediv 2 / fbdiv 28, measured 0.005 px — a hundredfold, reproduced twice live and again from a cold boot with the fix in the image.
The likely mechanism is the prediv rather than the frequency: dividing 24 MHz by 12 runs the PLL phase detector at 2 MHz, where dividing by 2 runs it at 12 MHz, and a loop that compares phases six times less often is a jittery one. Two instrument lessons came out of it that I would now apply anywhere: a hand-held camera measures the hand — the first recording captured plus or minus 2 px of my own pulse, because a rolling shutter turns tremor into exactly the artifact being hunted — and to know whether a picture is changing at all, hash the scanout buffers rather than trusting a camera.
Two stacked reasons the touchscreen did not work
Touch never worked on my kernel, and it took two separate findings to fix. The Silead GSL3673's reset line sat low and the chip refused every i2c read, because the kernel command line carried `consoleblank=600`: ten idle minutes after boot, fbcon blanks the framebuffer, the vendor driver's framebuffer-blank notifier suspends the touch controller, and nothing ever unblanks a KMS appliance that does not use fbcon. The init program now unbinds fbcon before starting anything.
With the reset released the chip ran and still reported no finger, because the vendor tree ships another panel's firmware for it: 4950 records with a resolution word of 0x08000600, where the array extracted from this tablet's own stock kernel image has 4719 and 0x02580400. Installing the stock arrays fixed it. The general lesson is the one this whole project kept repeating: the vendor tree is evidence about some board, not necessarily about yours.
Where it stands, and what is still rough
- On September 17, 2026, I confirmed Linux 7.3 and a working touchscreen DMX desk for my lighting rig. My own qualification, kept because it is the honest state: there are still rough edges to file down, and the thing does its job.
- The system is a Buildroot 2026.02.3 image with BusyBox; the appliance, the diagnostics and the GPU demo ship inside it rather than being rebuilt and copied in each time.
- The tablet knows which way up it is. The device tree names an accelerometer the kernel has no driver for; its WHO_AM_I reads 0x11, which makes it a Silan SC7A20, LIS3DH-compatible, driven directly over /dev/i2c-2. Gravity along the short axis flips the picture, the status bar and the touch coordinates.
- The way back never depended on the work being correct: a stock-kernel rescue lives in the recovery partition, proved by an actual round trip rather than assumed, and the USB console is the route in that does not need WiFi.
- The whole thing is open source at github.com/spectalive/taq102, GPL-2.0: the Buildroot tree, the appliance, the device tree, the kernel patches and the host tests. It ships no vendor binaries, because the Realtek driver and the Silead touchscreen firmware are not mine to redistribute; the repository says how to pull each one off a device you own. The kernel work is checkable independently: the patches and the review thread are on lore.kernel.org under my name.
- Next, and the reason this is written now: the screen calibration was done by eye, one test pattern at a time. The measurement described above is the beginning of taking the human out of that loop — pointing a camera at the panel and letting the machine decide whether the picture is right.