From 7a1d9a9f0e907f5afaf534993393efff0718dab1 Mon Sep 17 00:00:00 2001 From: Joakim Date: Sun, 3 May 2026 00:36:59 +0200 Subject: [PATCH] N/A --- a | 245 ++++++++++++++++++ .../0001-drm-panel-jinglitai-jlt4013a.patch | 16 -- br2_external/configs/mestre_x6200_defconfig | 4 +- 3 files changed, 247 insertions(+), 18 deletions(-) create mode 100644 a diff --git a/a b/a new file mode 100644 index 0000000..e72a32e --- /dev/null +++ b/a @@ -0,0 +1,245 @@ +Adds driver for the Jinglitai JLT4013A LCD panel used in the Xiegu X6200. + +This patch was written against a ~6.1-era kernel. It may require minor +forward-porting for 6.6 (panel/Kconfig line offsets may have shifted as +new panel drivers were added upstream). The core driver file +(panel-jinglitai-jlt4013a.c) should apply cleanly. + +NOTE: Milestone 1 (serial console boot) does not require this patch. +If the patch fails to apply, comment out BR2_LINUX_KERNEL_PATCH in the +defconfig and address the LCD driver in Milestone 2. +--- +-- ++++ my/drivers/gpu/drm/panel/Makefile 2023-01-30 03:23:34.824674091 +0300 +@@ -73,3 +73,4 @@ + obj-$(CONFIG_DRM_PANEL_VISIONOX_RM69299) += panel-visionox-rm69299.o + obj-$(CONFIG_DRM_PANEL_WIDECHIPS_WS2401) += panel-widechips-ws2401.o + obj-$(CONFIG_DRM_PANEL_XINPENG_XPP055C272) += panel-xinpeng-xpp055c272.o ++obj-$(CONFIG_DRM_PANEL_JINGLITAI_JLT4013A) += panel-jinglitai-jlt4013a.o +diff -Naur orig/drivers/gpu/drm/panel/panel-jinglitai-jlt4013a.c my/drivers/gpu/drm/panel/panel-jinglitai-jlt4013a.c +--- orig/drivers/gpu/drm/panel/panel-jinglitai-jlt4013a.c 1970-01-01 03:00:00.000000000 +0300 ++++ my/drivers/gpu/drm/panel/panel-jinglitai-jlt4013a.c 2023-01-30 03:22:15.521007934 +0300 +@@ -0,0 +1,549 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Driver for the Jinglitai JLT4013A LCD Panel. ++ * +-- ++ val); \ ++ return val; \ ++ } \ ++ } while (0) ++ ++static const struct of_device_id jlt4013a_of_match[] = { ++ { .compatible = "sitronix,st7701s" }, ++ { .compatible = "jinglitai,jlt4013a" }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, jlt4013a_of_match); ++ ++static const struct drm_display_mode jlt4013a_default_display_mode = { ++ .clock = 27500, ++ .hdisplay = 480, /* x */ ++ .hsync_start = 480 + 38, /* x + ri */ ++ .hsync_end = 480 + 38 + 12, /* x + ri + hs */ ++ .htotal = 480 + 38 + 12 + 12, /* x + ri + hs + le */ +-- ++ .width_mm = 52, ++ .height_mm = 86, ++}; ++ ++ ++struct jlt4013a { ++ struct drm_panel panel; ++ struct spi_device *spi; ++ struct gpio_desc *reset; ++ struct gpio_desc *dcx; ++ struct regulator *supply; ++}; ++ ++static int st7701s_spi_write(struct jlt4013a *ctx, u8 data) ++{ ++ struct spi_transfer xfer = {}; ++ struct spi_message msg; ++ ++ spi_message_init(&msg); +-- ++ ++ spi_message_add_tail(&xfer, &msg); ++ return spi_sync(ctx->spi, &msg); ++} ++ ++static int st7701s_write_command(struct jlt4013a *ctx, u8 cmd) ++{ ++ // pr_info("Jinglitai JLT4013A: Writing SPI command with value %x\n", cmd); ++ ++ gpiod_set_value(ctx->dcx, 0); ++ ++ return st7701s_spi_write(ctx, cmd); ++} ++ ++static int st7701s_write_data(struct jlt4013a *ctx, u8 cmd) ++{ ++ // pr_info("Jinglitai JLT4013A: Writing SPI data with value %x\n", cmd); ++ ++ gpiod_set_value(ctx->dcx, 1); ++ ++ return st7701s_spi_write(ctx, cmd); ++} ++ ++static inline struct jlt4013a *panel_to_jlt4013a(struct drm_panel *panel) ++{ ++ return container_of(panel, struct jlt4013a, panel); ++} ++ ++static int jlt4013a_prepare(struct drm_panel *panel) ++{ ++ int ret; ++ struct jlt4013a *ctx = panel_to_jlt4013a(panel); ++ ++ /* Enable power supply */ ++ ++ pr_info("Jinglitai JLT4013A: Trying to enable power supply\n"); ++ ret = regulator_enable(ctx->supply); +-- ++ ST7701S_TRY(ret, st7701s_write_data(ctx, 0x00)); ++ ST7701S_TRY(ret, st7701s_write_data(ctx, 0x10)); ++ ++ ST7701S_TRY(ret, st7701s_write_command(ctx, ST7701S_PORCTRL)); ++ ST7701S_TRY(ret, st7701s_write_data(ctx, ++ jlt4013a_default_display_mode.vtotal ++ - jlt4013a_default_display_mode.vsync_end)); // mode.vtotal - mode.vsync_end ++ ST7701S_TRY(ret, st7701s_write_data(ctx, ++ jlt4013a_default_display_mode.vsync_start ++ - jlt4013a_default_display_mode.vdisplay)); // mode.vsync_start - mode.vdisplay ++ ++ ST7701S_TRY(ret, st7701s_write_command(ctx, ST7701S_INVSET)); ++ ST7701S_TRY(ret, st7701s_write_data(ctx, 0x31)); ++ ST7701S_TRY(ret, st7701s_write_data(ctx, 0x03)); ++ ++ ST7701S_TRY(ret, st7701s_write_command(ctx, 0xC3)); ++ ST7701S_TRY(ret, st7701s_write_data(ctx, 0x02)); // DataPolarity: negative (The data is input on the negative edge of DOTCLK) ++ ST7701S_TRY(ret, st7701s_write_data(ctx, ++ jlt4013a_default_display_mode.htotal ++ - jlt4013a_default_display_mode.hsync_end)); // HBP = mode.htotal - mode.hsync_end ++ ST7701S_TRY(ret, st7701s_write_data(ctx, ++ jlt4013a_default_display_mode.vsync_start ++ - jlt4013a_default_display_mode.vdisplay)); // VBP = mode.vsync_start - mode.vdisplay ++ ++ /* Something strange */ ++ ++ ST7701S_TRY(ret, st7701s_write_command(ctx, 0xCC)); ++ ST7701S_TRY(ret, st7701s_write_data(ctx, 0x10)); +-- ++ ++ pr_info("Jinglitai JLT4013A: Panel is initialized\n"); ++ return ret; ++} ++ ++static int jlt4013a_unprepare(struct drm_panel *panel) ++{ ++ struct jlt4013a *ctx = panel_to_jlt4013a(panel); ++ ++ int ret = regulator_disable(ctx->supply); ++ return ret; ++} ++ ++ ++static int jlt4013a_get_modes(struct drm_panel *panel, ++ struct drm_connector *connector) ++{ ++ static const u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; ++ static const u32 bus_flags = DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE; ++ ++ ++ struct drm_display_mode *mode = drm_mode_duplicate( ++ connector->dev, &jlt4013a_default_display_mode); ++ if (mode == NULL) { ++ dev_err(panel->dev, ++ "Jinglitai JLT4013A: Failed to add default mode\n"); ++ return -EAGAIN; ++ } +-- ++ 1); ++ ++ return 1; ++} ++ ++static int jlt4013a_enable(struct drm_panel *panel) ++{ ++ return 0; ++} ++ ++static int jlt4013a_disable(struct drm_panel *panel) ++{ ++ return 0; ++} ++ ++static const struct drm_panel_funcs jlt4013afuncs = { ++ .prepare = jlt4013a_prepare, ++ .unprepare = jlt4013a_unprepare, ++ .get_modes = jlt4013a_get_modes, ++ .enable = jlt4013a_enable, ++ .disable = jlt4013a_disable, ++}; ++ ++static int jlt4013a_probe(struct spi_device *spi) ++{ ++ int err; ++ ++ struct device *dev = &spi->dev; ++ ++ struct jlt4013a *ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL); ++ if (ctx == NULL) { ++ return -EAGAIN; ++ } ++ ++ ctx->spi = spi; +-- ++ if (IS_ERR(ctx->dcx)) { ++ dev_err(dev, "Jinglitai JLT4013A: Failed to get dcx GPIO\n"); ++ return PTR_ERR(ctx->dcx); ++ } ++ ++ drm_panel_init(&ctx->panel, dev, &jlt4013afuncs, ++ DRM_MODE_CONNECTOR_DPI); ++ ++ err = drm_panel_of_backlight(&ctx->panel); ++ if (err) ++ return err; +-- ++ ++ return 0; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0) ++static void jlt4013a_remove(struct spi_device *spi) ++{ ++ struct jlt4013a *ctx = spi_get_drvdata(spi); ++ ++ drm_panel_remove(&(ctx->panel)); ++} ++#else ++static int jlt4013a_remove(struct spi_device *spi) ++{ ++ struct jlt4013a *ctx = spi_get_drvdata(spi); ++ ++ drm_panel_remove(&(ctx->panel)); ++ return 0; ++} ++#endif ++ ++static struct spi_driver jlt4013a_driver = { ++ .probe = jlt4013a_probe, ++ .remove = jlt4013a_remove, ++ .driver = { ++ .name = "jlt4013a", ++ .of_match_table = jlt4013a_of_match, ++ }, ++}; ++module_spi_driver(jlt4013a_driver); ++ ++MODULE_AUTHOR("Rui Oliveira "); ++MODULE_AUTHOR("Oleg Belousov "); ++MODULE_DESCRIPTION("Driver for the Jinglitai JLT4013A LCD Panel"); ++MODULE_LICENSE("GPL v2"); diff --git a/br2_external/board/x6200/linux/patches/0001-drm-panel-jinglitai-jlt4013a.patch b/br2_external/board/x6200/linux/patches/0001-drm-panel-jinglitai-jlt4013a.patch index 0687848..b45df11 100644 --- a/br2_external/board/x6200/linux/patches/0001-drm-panel-jinglitai-jlt4013a.patch +++ b/br2_external/board/x6200/linux/patches/0001-drm-panel-jinglitai-jlt4013a.patch @@ -1,19 +1,3 @@ -From: Vendored from gdyuldin/AetherX6200Buildroot (GPL-2.0) -Source: https://github.com/gdyuldin/AetherX6200Buildroot -Original authors: Rui Oliveira (2022), Oleg Belousov (2022) - -Adds driver for the Jinglitai JLT4013A LCD panel used in the Xiegu X6200. - -This patch was written against a ~6.1-era kernel. It may require minor -forward-porting for 6.6 (panel/Kconfig line offsets may have shifted as -new panel drivers were added upstream). The core driver file -(panel-jinglitai-jlt4013a.c) should apply cleanly. - -NOTE: Milestone 1 (serial console boot) does not require this patch. -If the patch fails to apply, comment out BR2_LINUX_KERNEL_PATCH in the -defconfig and address the LCD driver in Milestone 2. ---- - diff -Naur orig/drivers/gpu/drm/panel/Kconfig my/drivers/gpu/drm/panel/Kconfig --- orig/drivers/gpu/drm/panel/Kconfig 2023-01-12 14:00:49.000000000 +0300 +++ my/drivers/gpu/drm/panel/Kconfig 2023-01-30 03:24:48.108365590 +0300 diff --git a/br2_external/configs/mestre_x6200_defconfig b/br2_external/configs/mestre_x6200_defconfig index 302eda9..274d7c3 100644 --- a/br2_external/configs/mestre_x6200_defconfig +++ b/br2_external/configs/mestre_x6200_defconfig @@ -56,8 +56,8 @@ BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BR2_EXTERNAL_MESTRE_PATH)/board/x6200/genimage # for 6.6. Milestone 1 (serial console) does not require the LCD driver. BR2_LINUX_KERNEL=y BR2_LINUX_KERNEL_CUSTOM_VERSION=y -BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.66" -BR2_KERNEL_HEADERS_6_6=y +BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.82" +BR2_KERNEL_HEADERS_6_1=y BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="$(BR2_EXTERNAL_MESTRE_PATH)/board/x6200/linux/linux.config" BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_MESTRE_PATH)/board/x6200/linux/linux-midi.fragment"