Created
May 4, 2026 08:25
-
-
Save devsnek/2184bfe1f1be3d1f4fee0b69edc337c2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From 399ffde6b7f27efd0b492fadc240bdce41174824 Mon Sep 17 00:00:00 2001 | |
| From: snek <the@snek.dev> | |
| Date: Mon, 4 May 2026 09:44:07 +0200 | |
| Subject: [PATCH] mipi-dbi | |
| --- | |
| .../base-files/lib/firmware/ubnt,utr-lcd.bin | Bin 0 -> 93 bytes | |
| target/linux/ipq40xx/dts/qcom-ipq4018-utr.dts | 32 ++- | |
| target/linux/ipq40xx/image/generic.mk | 2 +- | |
| .../875-fb-st7789v-geometry.patch | 197 ------------------ | |
| 4 files changed, 23 insertions(+), 208 deletions(-) | |
| create mode 100644 target/linux/ipq40xx/base-files/lib/firmware/ubnt,utr-lcd.bin | |
| delete mode 100644 target/linux/ipq40xx/patches-6.12/875-fb-st7789v-geometry.patch | |
| diff --git a/target/linux/ipq40xx/base-files/lib/firmware/ubnt,utr-lcd.bin b/target/linux/ipq40xx/base-files/lib/firmware/ubnt,utr-lcd.bin | |
| new file mode 100644 | |
| index 0000000000000000000000000000000000000000..252ab55287667c9c3d786483757b4bec24240491 | |
| GIT binary patch | |
| literal 93 | |
| zcmebE4DeKNaq?t<07gLu2F402MpiS%1DjY`Ss9Ftw=<URW>h-F#Q6U(qwo<%g`<oL | |
| n7nqhTe86{sm5Y;uRnNthUtCPv_#uq%?8+}DrfsaqpveFLtq2rB | |
| literal 0 | |
| HcmV?d00001 | |
| diff --git a/target/linux/ipq40xx/dts/qcom-ipq4018-utr.dts b/target/linux/ipq40xx/dts/qcom-ipq4018-utr.dts | |
| index 9cfb52e8ba..2297ed605e 100644 | |
| --- a/target/linux/ipq40xx/dts/qcom-ipq4018-utr.dts | |
| +++ b/target/linux/ipq40xx/dts/qcom-ipq4018-utr.dts | |
| @@ -15,10 +15,12 @@ | |
| }; | |
| chosen { | |
| - bootargs-append = " ubi.mtd=kernel1 root=/dev/ubiblock0_1 rootfstype=squashfs"; | |
| + stdout-path = "serial0:115200n8"; | |
| + bootargs-append = " ubi.mtd=kernel1 root=/dev/ubiblock0_1 rootfstype=squashfs clk_ignore_unused"; | |
| }; | |
| aliases { | |
| + serial0 = &blsp1_uart1; | |
| ethernet0 = &gmac; | |
| }; | |
| @@ -234,18 +236,28 @@ | |
| }; | |
| display@2 { | |
| - compatible = "sitronix,st7789v"; | |
| + compatible = "ubnt,utr-lcd", "panel-mipi-dbi-spi"; | |
| reg = <2>; | |
| spi-max-frequency = <24000000>; | |
| - buswidth = <8>; | |
| dc-gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>; | |
| - reset-gpios = <&tlmm 0 GPIO_ACTIVE_LOW>; | |
| - backlight = <&backlight>; | |
| - panel-width = <135>; | |
| - panel-height = <240>; | |
| - x-offset = <52>; | |
| - y-offset = <39>; | |
| - rotate = <180>; | |
| + reset-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>; | |
| + /*backlight = <&backlight>;*/ | |
| + write-only; | |
| + | |
| + width-mm = <14>; | |
| + height-mm = <25>; | |
| + | |
| + panel-timing { | |
| + hactive = <136>; | |
| + vactive = <240>; | |
| + hback-porch = <53>; | |
| + vback-porch = <40>; | |
| + clock-frequency = <0>; | |
| + hfront-porch = <0>; | |
| + hsync-len = <0>; | |
| + vfront-porch = <0>; | |
| + vsync-len = <0>; | |
| + }; | |
| }; | |
| }; | |
| diff --git a/target/linux/ipq40xx/image/generic.mk b/target/linux/ipq40xx/image/generic.mk | |
| index 9cbeea06bb..8fb049e069 100644 | |
| --- a/target/linux/ipq40xx/image/generic.mk | |
| +++ b/target/linux/ipq40xx/image/generic.mk | |
| @@ -1284,7 +1284,7 @@ define Device/ubnt_utr | |
| PAGESIZE := 2048 | |
| KERNEL_IN_UBI := | |
| UBINIZE_PARTS = vol=$(KDIR)/ubnt_utr-uImage.itb | |
| - DEVICE_PACKAGES := kmod-fb-tft-st7789v kmod-bluetooth kmod-btusb | |
| + DEVICE_PACKAGES := kmod-drm-panel-mipi-dbi kmod-gpio-backlight kmod-bluetooth kmod-btusb | |
| endef | |
| TARGET_DEVICES += ubnt_utr | |
| diff --git a/target/linux/ipq40xx/patches-6.12/875-fb-st7789v-geometry.patch b/target/linux/ipq40xx/patches-6.12/875-fb-st7789v-geometry.patch | |
| deleted file mode 100644 | |
| index 870ef04941..0000000000 | |
| --- a/target/linux/ipq40xx/patches-6.12/875-fb-st7789v-geometry.patch | |
| +++ /dev/null | |
| @@ -1,197 +0,0 @@ | |
| -From: Matt Eaton <linux@divinehawk.com> | |
| -Subject: [PATCH] staging: fbtft: st7789v: add configurable panel geometry and offset | |
| - | |
| -Add device-tree-driven panel geometry and a fixed x/y offset for the | |
| -addr-window. Pad xres_virtual up to a 32-bit boundary so fbcon's | |
| -sys_imageblit slow path doesn't scatter glyph rows when the visible | |
| -width isn't word-aligned at the framebuffer's bpp; trim each row back | |
| -to the visible width before shipping pixels to the panel. | |
| - | |
| -Signed-off-by: Matt Eaton <linux@divinehawk.com> | |
| ---- | |
| - drivers/staging/fbtft/fb_st7789v.c | 146 ++++++++++++++++++++++ | |
| - 1 file changed, 126 insertions(+), 20 deletions(-) | |
| - | |
| ---- a/drivers/staging/fbtft/fb_st7789v.c | |
| -+++ b/drivers/staging/fbtft/fb_st7789v.c | |
| -@@ -76,6 +76,102 @@ | |
| - static struct completion panel_te; /* completion for panel TE line */ | |
| - static int irq_te; /* Linux IRQ for LCD TE line */ | |
| - | |
| -+struct st7789v_panel_cfg { | |
| -+ u16 panel_width; | |
| -+ u16 panel_height; | |
| -+ u16 x_offset; | |
| -+ u16 y_offset; | |
| -+}; | |
| -+ | |
| -+static int st7789v_init_panel_cfg(struct fbtft_par *par) | |
| -+{ | |
| -+ struct device *dev = par->info->device; | |
| -+ struct st7789v_panel_cfg *cfg; | |
| -+ u32 val; | |
| -+ | |
| -+ cfg = devm_kzalloc(dev, sizeof(*cfg), GFP_KERNEL); | |
| -+ if (!cfg) | |
| -+ return -ENOMEM; | |
| -+ | |
| -+ cfg->panel_width = 240; | |
| -+ cfg->panel_height = 320; | |
| -+ cfg->x_offset = 0; | |
| -+ cfg->y_offset = 0; | |
| -+ | |
| -+ if (!device_property_read_u32(dev, "panel-width", &val)) | |
| -+ cfg->panel_width = val; | |
| -+ if (!device_property_read_u32(dev, "panel-height", &val)) | |
| -+ cfg->panel_height = val; | |
| -+ if (!device_property_read_u32(dev, "x-offset", &val)) | |
| -+ cfg->x_offset = val; | |
| -+ if (!device_property_read_u32(dev, "y-offset", &val)) | |
| -+ cfg->y_offset = val; | |
| -+ | |
| -+ par->extra = cfg; | |
| -+ return 0; | |
| -+} | |
| -+ | |
| -+static void st7789v_apply_panel_cfg(struct fbtft_par *par) | |
| -+{ | |
| -+ struct st7789v_panel_cfg *cfg = par->extra; | |
| -+ unsigned int bpp = par->info->var.bits_per_pixel; | |
| -+ unsigned int xres_v; | |
| -+ | |
| -+ /* Pad xres_virtual so line_length is 32-bit aligned: fbcon's | |
| -+ * sys_imageblit slow path writes glyphs as u32 words and | |
| -+ * assumes each row starts at the same alignment, so a | |
| -+ * non-word-aligned stride scatters glyph rows horizontally. | |
| -+ */ | |
| -+ xres_v = round_up(cfg->panel_width * bpp, 32) / bpp; | |
| -+ | |
| -+ par->info->var.xres = cfg->panel_width; | |
| -+ par->info->var.yres = cfg->panel_height; | |
| -+ par->info->var.xres_virtual = xres_v; | |
| -+ par->info->var.yres_virtual = cfg->panel_height; | |
| -+ par->info->fix.line_length = xres_v * bpp / 8; | |
| -+ par->info->fix.smem_len = par->info->fix.line_length * | |
| -+ cfg->panel_height; | |
| -+} | |
| -+ | |
| -+static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) | |
| -+{ | |
| -+ struct st7789v_panel_cfg *cfg = par->extra; | |
| -+ | |
| -+ /* MADCTL_MX/MY/MV reverse the *write order* within the addr | |
| -+ * window; they don't translate the physical address mapping. | |
| -+ * The window therefore always stays at the panel's natural | |
| -+ * visible region regardless of rotation. | |
| -+ */ | |
| -+ xs += cfg->x_offset; xe += cfg->x_offset; | |
| -+ ys += cfg->y_offset; ye += cfg->y_offset; | |
| -+ | |
| -+ write_reg(par, MIPI_DCS_SET_COLUMN_ADDRESS, | |
| -+ (xs >> 8) & 0xff, xs & 0xff, | |
| -+ (xe >> 8) & 0xff, xe & 0xff); | |
| -+ write_reg(par, MIPI_DCS_SET_PAGE_ADDRESS, | |
| -+ (ys >> 8) & 0xff, ys & 0xff, | |
| -+ (ye >> 8) & 0xff, ye & 0xff); | |
| -+ write_reg(par, MIPI_DCS_WRITE_MEMORY_START); | |
| -+} | |
| -+ | |
| -+static int write_vmem_bus(struct fbtft_par *par, size_t offset, size_t len) | |
| -+{ | |
| -+ struct device *dev = par->info->device; | |
| -+ | |
| -+ switch (par->pdata->display.buswidth) { | |
| -+ case 8: | |
| -+ return fbtft_write_vmem16_bus8(par, offset, len); | |
| -+ case 9: | |
| -+ return fbtft_write_vmem16_bus9(par, offset, len); | |
| -+ case 16: | |
| -+ return fbtft_write_vmem16_bus16(par, offset, len); | |
| -+ default: | |
| -+ dev_err(dev, "Unsupported buswidth %d\n", | |
| -+ par->pdata->display.buswidth); | |
| -+ return 0; | |
| -+ } | |
| -+} | |
| -+ | |
| - static irqreturn_t panel_te_handler(int irq, void *data) | |
| - { | |
| - complete(&panel_te); | |
| -@@ -214,6 +310,13 @@ | |
| - if (HSD20_IPS) | |
| - write_reg(par, MIPI_DCS_ENTER_INVERT_MODE); | |
| - | |
| -+ if (!par->extra) { | |
| -+ rc = st7789v_init_panel_cfg(par); | |
| -+ if (rc) | |
| -+ return rc; | |
| -+ } | |
| -+ st7789v_apply_panel_cfg(par); | |
| -+ | |
| - return 0; | |
| - } | |
| - | |
| -@@ -228,7 +331,9 @@ | |
| - static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) | |
| - { | |
| - struct device *dev = par->info->device; | |
| -- int ret; | |
| -+ struct st7789v_panel_cfg *cfg = par->extra; | |
| -+ size_t row_bytes, stride, sent; | |
| -+ int ret = 0; | |
| - | |
| - if (irq_te) { | |
| - enable_irq(irq_te); | |
| -@@ -241,21 +346,21 @@ | |
| - disable_irq(irq_te); | |
| - } | |
| - | |
| -- switch (par->pdata->display.buswidth) { | |
| -- case 8: | |
| -- ret = fbtft_write_vmem16_bus8(par, offset, len); | |
| -- break; | |
| -- case 9: | |
| -- ret = fbtft_write_vmem16_bus9(par, offset, len); | |
| -- break; | |
| -- case 16: | |
| -- ret = fbtft_write_vmem16_bus16(par, offset, len); | |
| -- break; | |
| -- default: | |
| -- dev_err(dev, "Unsupported buswidth %d\n", | |
| -- par->pdata->display.buswidth); | |
| -- ret = 0; | |
| -- break; | |
| -+ stride = par->info->fix.line_length; | |
| -+ row_bytes = cfg ? (size_t)cfg->panel_width * | |
| -+ par->info->var.bits_per_pixel / 8 : stride; | |
| -+ | |
| -+ if (row_bytes == stride) | |
| -+ return write_vmem_bus(par, offset, len); | |
| -+ | |
| -+ /* line_length is padded so sys_imageblit stays 32-bit aligned | |
| -+ * across rows; ship only the visible portion of each row and | |
| -+ * skip the trailing pad bytes. | |
| -+ */ | |
| -+ for (sent = 0; sent < len; sent += stride) { | |
| -+ ret = write_vmem_bus(par, offset + sent, row_bytes); | |
| -+ if (ret < 0) | |
| -+ return ret; | |
| - } | |
| - | |
| - return ret; | |
| -@@ -375,10 +480,11 @@ | |
| - .gamma = HSD20_IPS_GAMMA, | |
| - .fbtftops = { | |
| - .init_display = init_display, | |
| -- .write_vmem = write_vmem, | |
| -- .set_var = set_var, | |
| -- .set_gamma = set_gamma, | |
| -- .blank = blank, | |
| -+ .write_vmem = write_vmem, | |
| -+ .set_addr_win = set_addr_win, | |
| -+ .set_var = set_var, | |
| -+ .set_gamma = set_gamma, | |
| -+ .blank = blank, | |
| - }, | |
| - }; | |
| - | |
| -- | |
| 2.54.0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment