N/A
This commit is contained in:
245
a
Normal file
245
a
Normal file
@@ -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 <ruimail24@gmail.com>");
|
||||||
|
+MODULE_AUTHOR("Oleg Belousov <www.strijar.ru>");
|
||||||
|
+MODULE_DESCRIPTION("Driver for the Jinglitai JLT4013A LCD Panel");
|
||||||
|
+MODULE_LICENSE("GPL v2");
|
||||||
@@ -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
|
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
|
--- 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
|
+++ my/drivers/gpu/drm/panel/Kconfig 2023-01-30 03:24:48.108365590 +0300
|
||||||
|
|||||||
@@ -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.
|
# for 6.6. Milestone 1 (serial console) does not require the LCD driver.
|
||||||
BR2_LINUX_KERNEL=y
|
BR2_LINUX_KERNEL=y
|
||||||
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
|
||||||
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.66"
|
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.1.82"
|
||||||
BR2_KERNEL_HEADERS_6_6=y
|
BR2_KERNEL_HEADERS_6_1=y
|
||||||
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=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_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"
|
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_MESTRE_PATH)/board/x6200/linux/linux-midi.fragment"
|
||||||
|
|||||||
Reference in New Issue
Block a user