From 2dfb5d952ef3a6cdb73c04bd64a85db5ce6968f6 Mon Sep 17 00:00:00 2001 From: FrankLeeEDA Date: Thu, 4 Jun 2026 13:54:25 +0000 Subject: [PATCH 1/4] drm/panel: ilitek-ili9881c: Add support for edatec 101c panel Add support for the edatec 101c (800x1280) DSI panel. This panel uses the ILI9881C driver IC and is compatible with the existing initialization sequence defined in the driver. Signed-off-by: FrankLeeEDA --- drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c index fe8964d9f8f04f..3346bfeb5e5a34 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9881c.c @@ -2230,6 +2230,211 @@ static const struct ili9881c_instr bsd1218_a101kl68_init[] = { ILI9881C_COMMAND_INSTR(0xd3, 0x3f), }; +static const struct ili9881c_instr t101p136cq_init[] = { + ILI9881C_SWITCH_PAGE_INSTR(3), + ILI9881C_COMMAND_INSTR(0x01, 0x00), + ILI9881C_COMMAND_INSTR(0x02, 0x00), + ILI9881C_COMMAND_INSTR(0x03, 0x53), + ILI9881C_COMMAND_INSTR(0x04, 0x53), + ILI9881C_COMMAND_INSTR(0x05, 0x13), + ILI9881C_COMMAND_INSTR(0x06, 0x04), + ILI9881C_COMMAND_INSTR(0x07, 0x02), + ILI9881C_COMMAND_INSTR(0x08, 0x02), + ILI9881C_COMMAND_INSTR(0x09, 0x00), + ILI9881C_COMMAND_INSTR(0x0A, 0x00), + ILI9881C_COMMAND_INSTR(0x0B, 0x00), + ILI9881C_COMMAND_INSTR(0x0C, 0x00), + ILI9881C_COMMAND_INSTR(0x0D, 0x00), + ILI9881C_COMMAND_INSTR(0x0E, 0x00), + ILI9881C_COMMAND_INSTR(0x0F, 0x00), + ILI9881C_COMMAND_INSTR(0x10, 0x00), + ILI9881C_COMMAND_INSTR(0x11, 0x00), + ILI9881C_COMMAND_INSTR(0x12, 0x00), + ILI9881C_COMMAND_INSTR(0x13, 0x00), + ILI9881C_COMMAND_INSTR(0x14, 0x00), + ILI9881C_COMMAND_INSTR(0x15, 0x05), + ILI9881C_COMMAND_INSTR(0x16, 0x05), + ILI9881C_COMMAND_INSTR(0x17, 0x03), + ILI9881C_COMMAND_INSTR(0x18, 0x03), + ILI9881C_COMMAND_INSTR(0x19, 0x00), + ILI9881C_COMMAND_INSTR(0x1A, 0x00), + ILI9881C_COMMAND_INSTR(0x1B, 0x00), + ILI9881C_COMMAND_INSTR(0x1C, 0x00), + ILI9881C_COMMAND_INSTR(0x1D, 0x00), + ILI9881C_COMMAND_INSTR(0x1E, 0xC0), + ILI9881C_COMMAND_INSTR(0x1F, 0x80), + ILI9881C_COMMAND_INSTR(0x20, 0x02), + ILI9881C_COMMAND_INSTR(0x21, 0x09), + ILI9881C_COMMAND_INSTR(0x22, 0x00), + ILI9881C_COMMAND_INSTR(0x23, 0x00), + ILI9881C_COMMAND_INSTR(0x24, 0x00), + ILI9881C_COMMAND_INSTR(0x25, 0x00), + ILI9881C_COMMAND_INSTR(0x26, 0x00), + ILI9881C_COMMAND_INSTR(0x27, 0x00), + ILI9881C_COMMAND_INSTR(0x28, 0x55), + ILI9881C_COMMAND_INSTR(0x29, 0x03), + ILI9881C_COMMAND_INSTR(0x2A, 0x00), + ILI9881C_COMMAND_INSTR(0x2B, 0x00), + ILI9881C_COMMAND_INSTR(0x2C, 0x00), + ILI9881C_COMMAND_INSTR(0x2D, 0x00), + ILI9881C_COMMAND_INSTR(0x2E, 0x00), + ILI9881C_COMMAND_INSTR(0x2F, 0x00), + ILI9881C_COMMAND_INSTR(0x30, 0x00), + ILI9881C_COMMAND_INSTR(0x31, 0x00), + ILI9881C_COMMAND_INSTR(0x32, 0x00), + ILI9881C_COMMAND_INSTR(0x33, 0x00), + ILI9881C_COMMAND_INSTR(0x34, 0x00), + ILI9881C_COMMAND_INSTR(0x35, 0x00), + ILI9881C_COMMAND_INSTR(0x36, 0x00), + ILI9881C_COMMAND_INSTR(0x37, 0x00), + ILI9881C_COMMAND_INSTR(0x38, 0x3C), + ILI9881C_COMMAND_INSTR(0x39, 0x00), + ILI9881C_COMMAND_INSTR(0x3A, 0x00), + ILI9881C_COMMAND_INSTR(0x3B, 0x00), + ILI9881C_COMMAND_INSTR(0x3C, 0x00), + ILI9881C_COMMAND_INSTR(0x3D, 0x00), + ILI9881C_COMMAND_INSTR(0x3E, 0x00), + ILI9881C_COMMAND_INSTR(0x3F, 0x00), + ILI9881C_COMMAND_INSTR(0x40, 0x00), + ILI9881C_COMMAND_INSTR(0x41, 0x00), + ILI9881C_COMMAND_INSTR(0x42, 0x00), + ILI9881C_COMMAND_INSTR(0x43, 0x00), + ILI9881C_COMMAND_INSTR(0x44, 0x00), + ILI9881C_COMMAND_INSTR(0x50, 0x01), + ILI9881C_COMMAND_INSTR(0x51, 0x23), + ILI9881C_COMMAND_INSTR(0x52, 0x45), + ILI9881C_COMMAND_INSTR(0x53, 0x67), + ILI9881C_COMMAND_INSTR(0x54, 0x89), + ILI9881C_COMMAND_INSTR(0x55, 0xAB), + ILI9881C_COMMAND_INSTR(0x56, 0x01), + ILI9881C_COMMAND_INSTR(0x57, 0x23), + ILI9881C_COMMAND_INSTR(0x58, 0x45), + ILI9881C_COMMAND_INSTR(0x59, 0x67), + ILI9881C_COMMAND_INSTR(0x5A, 0x89), + ILI9881C_COMMAND_INSTR(0x5B, 0xAB), + ILI9881C_COMMAND_INSTR(0x5C, 0xCD), + ILI9881C_COMMAND_INSTR(0x5D, 0xEF), + ILI9881C_COMMAND_INSTR(0x5E, 0x01), + ILI9881C_COMMAND_INSTR(0x5F, 0x0A), + ILI9881C_COMMAND_INSTR(0x60, 0x02), + ILI9881C_COMMAND_INSTR(0x61, 0x02), + ILI9881C_COMMAND_INSTR(0x62, 0x08), + ILI9881C_COMMAND_INSTR(0x63, 0x15), + ILI9881C_COMMAND_INSTR(0x64, 0x14), + ILI9881C_COMMAND_INSTR(0x65, 0x02), + ILI9881C_COMMAND_INSTR(0x66, 0x11), + ILI9881C_COMMAND_INSTR(0x67, 0x10), + ILI9881C_COMMAND_INSTR(0x68, 0x02), + ILI9881C_COMMAND_INSTR(0x69, 0x0F), + ILI9881C_COMMAND_INSTR(0x6A, 0x0E), + ILI9881C_COMMAND_INSTR(0x6B, 0x02), + ILI9881C_COMMAND_INSTR(0x6C, 0x0D), + ILI9881C_COMMAND_INSTR(0x6D, 0x0C), + ILI9881C_COMMAND_INSTR(0x6E, 0x06), + ILI9881C_COMMAND_INSTR(0x6F, 0x02), + ILI9881C_COMMAND_INSTR(0x70, 0x02), + ILI9881C_COMMAND_INSTR(0x71, 0x02), + ILI9881C_COMMAND_INSTR(0x72, 0x02), + ILI9881C_COMMAND_INSTR(0x73, 0x02), + ILI9881C_COMMAND_INSTR(0x74, 0x02), + ILI9881C_COMMAND_INSTR(0x75, 0x0A), + ILI9881C_COMMAND_INSTR(0x76, 0x02), + ILI9881C_COMMAND_INSTR(0x77, 0x02), + ILI9881C_COMMAND_INSTR(0x78, 0x06), + ILI9881C_COMMAND_INSTR(0x79, 0x15), + ILI9881C_COMMAND_INSTR(0x7A, 0x14), + ILI9881C_COMMAND_INSTR(0x7B, 0x02), + ILI9881C_COMMAND_INSTR(0x7C, 0x10), + ILI9881C_COMMAND_INSTR(0x7D, 0x11), + ILI9881C_COMMAND_INSTR(0x7E, 0x02), + ILI9881C_COMMAND_INSTR(0x7F, 0x0C), + ILI9881C_COMMAND_INSTR(0x80, 0x0D), + ILI9881C_COMMAND_INSTR(0x81, 0x02), + ILI9881C_COMMAND_INSTR(0x82, 0x0E), + ILI9881C_COMMAND_INSTR(0x83, 0x0F), + ILI9881C_COMMAND_INSTR(0x84, 0x08), + ILI9881C_COMMAND_INSTR(0x85, 0x02), + ILI9881C_COMMAND_INSTR(0x86, 0x02), + ILI9881C_COMMAND_INSTR(0x87, 0x02), + ILI9881C_COMMAND_INSTR(0x88, 0x02), + ILI9881C_COMMAND_INSTR(0x89, 0x02), + ILI9881C_COMMAND_INSTR(0x8A, 0x02), + + ILI9881C_SWITCH_PAGE_INSTR(4), + ILI9881C_COMMAND_INSTR(0x3B, 0x98), + ILI9881C_COMMAND_INSTR(0x6C, 0x15), + ILI9881C_COMMAND_INSTR(0x6E, 0x30), + ILI9881C_COMMAND_INSTR(0x6F, 0x45), + ILI9881C_COMMAND_INSTR(0x8D, 0x1F), + ILI9881C_COMMAND_INSTR(0x87, 0xBA), + ILI9881C_COMMAND_INSTR(0x26, 0x76), + ILI9881C_COMMAND_INSTR(0xB2, 0xD1), + ILI9881C_COMMAND_INSTR(0x88, 0x0B), + ILI9881C_COMMAND_INSTR(0x21, 0xB0), + ILI9881C_COMMAND_INSTR(0x35, 0x17), + ILI9881C_COMMAND_INSTR(0x30, 0x01), + ILI9881C_COMMAND_INSTR(0x31, 0x75), + ILI9881C_COMMAND_INSTR(0xB5, 0x07), + ILI9881C_COMMAND_INSTR(0x8A, 0xD8), + ILI9881C_COMMAND_INSTR(0x3A, 0x8A), + + ILI9881C_SWITCH_PAGE_INSTR(1), + ILI9881C_COMMAND_INSTR(0x22, 0x0A), + ILI9881C_COMMAND_INSTR(0x31, 0x09), + ILI9881C_COMMAND_INSTR(0x40, 0x33), + ILI9881C_COMMAND_INSTR(0x42, 0x44), + ILI9881C_COMMAND_INSTR(0x53, 0x3E), + ILI9881C_COMMAND_INSTR(0x55, 0x45), + ILI9881C_COMMAND_INSTR(0x56, 0x00), + ILI9881C_COMMAND_INSTR(0x50, 0x95), + ILI9881C_COMMAND_INSTR(0x51, 0x95), + ILI9881C_COMMAND_INSTR(0x60, 0x09), + ILI9881C_COMMAND_INSTR(0x2E, 0xC8), + ILI9881C_COMMAND_INSTR(0x35, 0x07), + ILI9881C_COMMAND_INSTR(0x63, 0x00), + ILI9881C_COMMAND_INSTR(0xA0, 0x00), + ILI9881C_COMMAND_INSTR(0xA1, 0x14), + ILI9881C_COMMAND_INSTR(0xA2, 0x24), + ILI9881C_COMMAND_INSTR(0xA3, 0x17), + ILI9881C_COMMAND_INSTR(0xA4, 0x1A), + ILI9881C_COMMAND_INSTR(0xA5, 0x2C), + ILI9881C_COMMAND_INSTR(0xA6, 0x20), + ILI9881C_COMMAND_INSTR(0xA7, 0x1F), + ILI9881C_COMMAND_INSTR(0xA8, 0x81), + ILI9881C_COMMAND_INSTR(0xA9, 0x1E), + ILI9881C_COMMAND_INSTR(0xAA, 0x2A), + ILI9881C_COMMAND_INSTR(0xAB, 0x71), + ILI9881C_COMMAND_INSTR(0xAC, 0x19), + ILI9881C_COMMAND_INSTR(0xAD, 0x17), + ILI9881C_COMMAND_INSTR(0xAE, 0x4C), + ILI9881C_COMMAND_INSTR(0xAF, 0x1F), + ILI9881C_COMMAND_INSTR(0xB0, 0x26), + ILI9881C_COMMAND_INSTR(0xB1, 0x4D), + ILI9881C_COMMAND_INSTR(0xB2, 0x5D), + ILI9881C_COMMAND_INSTR(0xB3, 0x3F), + ILI9881C_COMMAND_INSTR(0xB7, 0x03), + ILI9881C_COMMAND_INSTR(0xC0, 0x00), + ILI9881C_COMMAND_INSTR(0xC1, 0x18), + ILI9881C_COMMAND_INSTR(0xC2, 0x24), + ILI9881C_COMMAND_INSTR(0xC3, 0x0E), + ILI9881C_COMMAND_INSTR(0xC4, 0x11), + ILI9881C_COMMAND_INSTR(0xC5, 0x24), + ILI9881C_COMMAND_INSTR(0xC6, 0x1A), + ILI9881C_COMMAND_INSTR(0xC7, 0x1E), + ILI9881C_COMMAND_INSTR(0xC8, 0x76), + ILI9881C_COMMAND_INSTR(0xC9, 0x1B), + ILI9881C_COMMAND_INSTR(0xCA, 0x27), + ILI9881C_COMMAND_INSTR(0xCB, 0x64), + ILI9881C_COMMAND_INSTR(0xCC, 0x19), + ILI9881C_COMMAND_INSTR(0xCD, 0x18), + ILI9881C_COMMAND_INSTR(0xCE, 0x4A), + ILI9881C_COMMAND_INSTR(0xCF, 0x20), + ILI9881C_COMMAND_INSTR(0xD0, 0x28), + ILI9881C_COMMAND_INSTR(0xD1, 0x4A), + ILI9881C_COMMAND_INSTR(0xD2, 0x5C), + ILI9881C_COMMAND_INSTR(0xD3, 0x3F), +}; + static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel) { return container_of(panel, struct ili9881c, panel); @@ -2511,6 +2716,23 @@ static const struct drm_display_mode bsd1218_a101kl68_default_mode = { .height_mm = 170, }; +static const struct drm_display_mode t101p136cq_mode = { + .clock = 78086, + + .hdisplay = 800, + .hsync_start = 800 + 120, + .hsync_end = 800 + 120 + 20, + .htotal = 800 + 120 + 20 + 40, + + .vdisplay = 1280, + .vsync_start = 1280 + 16, + .vsync_end = 1280 + 16 + 8, + .vtotal = 1280 + 16 + 8 + 24, + + .width_mm = 135, + .height_mm = 216, +}; + static int ili9881c_get_modes(struct drm_panel *panel, struct drm_connector *connector) { @@ -2719,6 +2941,14 @@ static const struct ili9881c_desc bsd1218_a101kl68_desc = { .lanes = 4, }; +static const struct ili9881c_desc t101p136cq_desc = { + .init = t101p136cq_init, + .init_length = ARRAY_SIZE(t101p136cq_init), + .mode = &t101p136cq_mode, + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM, + .lanes = 2, +}; + static const struct of_device_id ili9881c_of_match[] = { { .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc }, { .compatible = "bestar,bsd1218-a101kl68", .data = &bsd1218_a101kl68_desc }, @@ -2731,6 +2961,7 @@ static const struct of_device_id ili9881c_of_match[] = { { .compatible = "nwe,nwe080", .data = &nwe080_desc }, { .compatible = "raspberrypi,dsi-5inch", &rpi_5inch_desc }, { .compatible = "raspberrypi,dsi-7inch", &rpi_7inch_desc }, + { .compatible = "rzw,t101p136cq", .data = &t101p136cq_desc }, { } }; MODULE_DEVICE_TABLE(of, ili9881c_of_match); From 39112aefc03352eeb2e8f7794c444b1218965c43 Mon Sep 17 00:00:00 2001 From: FrankLeeEDA Date: Thu, 4 Jun 2026 14:11:21 +0000 Subject: [PATCH 2/4] regulator: edatec-panel-regulator: Add edatec panel regulator driver This driver provides support for controlling the panel's power supply, including the necessary voltage and current regulation for proper backlight and LCD operation. Signed-off-by: FrankLeeEDA --- drivers/regulator/Kconfig | 19 ++ drivers/regulator/Makefile | 1 + drivers/regulator/edatec-panel-regulator.c | 211 +++++++++++++++++++++ 3 files changed, 231 insertions(+) create mode 100644 drivers/regulator/edatec-panel-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b6ffd0d6ede856..21c8ce80ffa69d 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -1828,4 +1828,23 @@ config REGULATOR_QCOM_LABIBB boost regulator and IBB can be used as a negative boost regulator for LCD display panel. +config REGULATOR_EDATEC_PANEL + tristate "EDATEC panel regulator support" + depends on BACKLIGHT_CLASS_DEVICE + depends on I2C + select REGMAP_I2C + select GPIO_REGMAP + help + This driver provides support for controlling the panel's power supply, + including the necessary voltage and current regulation for proper + backlight and LCD operation. + + The driver communicates with the regulator hardware via the I2C bus. + Configuration is done through the Device Tree. You will need to enable + the appropriate Device Tree overlay or add the necessary node to your + Device Tree source file to make use of this driver. + + Say Y or M here if your system uses an EDATEC 101c/070c display panel. + Otherwise, say N. + endif diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index b0b8fd27799269..838ccb72bda382 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -211,5 +211,6 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o +obj-$(CONFIG_REGULATOR_EDATEC_PANEL) += edatec-panel-regulator.o ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG diff --git a/drivers/regulator/edatec-panel-regulator.c b/drivers/regulator/edatec-panel-regulator.c new file mode 100644 index 00000000000000..4227837466cbf2 --- /dev/null +++ b/drivers/regulator/edatec-panel-regulator.c @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2026 EDATEC + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_PWM 0x01 +#define REG_PWR 0x03 +#define REG_OUTPUT 0x0A +#define REG_BRIDGE_INIT 0x11 +#define REG_BACKLIGHT_EN 0x12 + +#define CMD_FW_VERSION 0xE1 + +enum gpio_signals { + PIN_LCD_BL_EN, + PIN_LCD_BL_PWM, + PIN_LCD_RST, + PIN_TP_RST, + PIN_LCD_VDD_EN, + NUM_GPIO +}; + +struct ed_regulator { + struct regmap *regmap; +}; + +static bool ed_readable_reg(struct device *dev, unsigned int reg) +{ + /* No registers are readable via the regmap. Use cached values */ + return false; +} + +static const struct regmap_config ed_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = REG_BACKLIGHT_EN, + .can_sleep = true, + .cache_type = REGCACHE_RBTREE, + .readable_reg = ed_readable_reg, +}; + +static int ed_update_status(struct backlight_device *bl) +{ + struct backlight_properties *props = &(bl->props); + struct ed_regulator *regulator = bl_get_data(bl); + struct regmap *regmap = regulator->regmap; + int brightness = backlight_get_brightness(bl); + int bl_power = props->power; + int ret; + + if (bl_power == 1 || bl_power == 4) + ret = regmap_write(regmap, REG_PWR, bl_power); + else + ret = regmap_write(regmap, REG_PWM, brightness); + + return ret; +} + +static const struct backlight_ops ed_bl = { + .update_status = ed_update_status, +}; + +static int ed_firmware_version(struct i2c_client *i2c) +{ + struct i2c_msg msgs[1]; + u8 addr_buf[1] = { CMD_FW_VERSION }; + u8 data_buf[16] = { 0 }; + int ret; + + msgs[0].addr = i2c->addr; + msgs[0].flags = 0; + msgs[0].len = 1; + msgs[0].buf = addr_buf; + + ret = i2c_transfer(i2c->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + usleep_range(200, 300); + + /* Read data from register */ + msgs[0].addr = i2c->addr; + msgs[0].flags = I2C_M_RD; + msgs[0].len = 16; + msgs[0].buf = data_buf; + + ret = i2c_transfer(i2c->adapter, msgs, ARRAY_SIZE(msgs)); + if (ret != ARRAY_SIZE(msgs)) + return -EIO; + + dev_info(&i2c->dev, "Firmware version: %s\n", data_buf); + + return 0; +} + +/* + * I2C driver interface functions + */ +static int ed_i2c_probe(struct i2c_client *i2c) +{ + struct gpio_regmap_config gconfig = { + .ngpio = NUM_GPIO, + .ngpio_per_reg = NUM_GPIO, + .parent = &i2c->dev, + .reg_set_base = REG_OUTPUT, + }; + struct backlight_properties props = { }; + struct backlight_device *bl; + struct ed_regulator *regulator; + struct regmap *regmap; + int ret; + + regulator = devm_kzalloc(&i2c->dev, sizeof(*regulator), GFP_KERNEL); + if (!regulator) + return -ENOMEM; + + ed_firmware_version(i2c); + + i2c_set_clientdata(i2c, regulator); + + regmap = devm_regmap_init_i2c(i2c, &ed_regmap_config); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + props.type = BACKLIGHT_RAW; + props.max_brightness = 0xff; + props.brightness = 0xff; + + regulator->regmap = regmap; + bl = devm_backlight_device_register(&i2c->dev, dev_name(&i2c->dev), + &i2c->dev, regulator, &ed_bl, &props); + if (IS_ERR(bl)) + return PTR_ERR(bl); + + bl->props.brightness = 0xff; + + ret = regmap_write(regmap, REG_OUTPUT, 0x00); + if (ret) { + dev_err(&i2c->dev, "Failed to initialise regmap values: %d\n", ret); + return ret; + } + + ret = regmap_write(regmap, REG_BRIDGE_INIT, 0x02); + if (ret) { + dev_err(&i2c->dev, "Failed to initialise panel bridge: %d\n", ret); + return ret; + } + + ret = regmap_write(regmap, REG_BACKLIGHT_EN, 0x01); + if (ret) { + dev_err(&i2c->dev, "Failed to enable backlight: %d\n", ret); + return ret; + } + + msleep(100); + + gconfig.regmap = regmap; + ret = PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&i2c->dev, &gconfig)); + if (ret) + return dev_err_probe(&i2c->dev, ret, "Failed to create gpiochip\n"); + + return 0; +} + +static void ed_i2c_shutdown(struct i2c_client *client) +{ + struct ed_regulator *regulator = i2c_get_clientdata(client); + + regmap_write(regulator->regmap, REG_OUTPUT, 0); + regmap_write(regulator->regmap, REG_BACKLIGHT_EN, 0); +} + +static const struct of_device_id ed_dt_ids[] = { + { .compatible = "edatec,disp-regulator" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ed_dt_ids); + +static struct i2c_driver ed_regulator_driver = { + .driver = { + .name = "edatec_panel_regulator", + .of_match_table = of_match_ptr(ed_dt_ids), + }, + .probe = ed_i2c_probe, + .shutdown = ed_i2c_shutdown, +}; +module_i2c_driver(ed_regulator_driver); + +MODULE_AUTHOR("EDATEC "); +MODULE_DESCRIPTION("EDATEC TFT LCD panel regulator driver"); +MODULE_LICENSE("GPL"); From f0530721f81397af1bc6e50f78c53fa41d781bfe Mon Sep 17 00:00:00 2001 From: FrankLeeEDA Date: Thu, 4 Jun 2026 14:19:01 +0000 Subject: [PATCH 3/4] arm64: defconfig: Enable CONFIG_REGULATOR_EDATEC_PANEL as module Enable the Edatec panel regulator driver as a loadable module in the following default configurations: - bcm2711_defconfig - bcm2711_rt_defconfig - bcm2712_defconfig This allows the kernel to support edatec display panels that require specific power sequencing controlled by this regulator driver. Signed-off-by: FrankLeeEDA --- arch/arm64/configs/bcm2711_defconfig | 1 + arch/arm64/configs/bcm2711_rt_defconfig | 1 + arch/arm64/configs/bcm2712_defconfig | 1 + 3 files changed, 3 insertions(+) diff --git a/arch/arm64/configs/bcm2711_defconfig b/arch/arm64/configs/bcm2711_defconfig index 8c386764a5e2b3..5f579b5dac414c 100644 --- a/arch/arm64/configs/bcm2711_defconfig +++ b/arch/arm64/configs/bcm2711_defconfig @@ -863,6 +863,7 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=m CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2=m CONFIG_REGULATOR_WAVESHARE_TOUCHSCREEN=m +CONFIG_REGULATOR_EDATEC_PANEL=m CONFIG_RC_CORE=y CONFIG_BPF_LIRC_MODE2=y CONFIG_LIRC=y diff --git a/arch/arm64/configs/bcm2711_rt_defconfig b/arch/arm64/configs/bcm2711_rt_defconfig index da41012a9c6c66..35c5333a38c8ba 100644 --- a/arch/arm64/configs/bcm2711_rt_defconfig +++ b/arch/arm64/configs/bcm2711_rt_defconfig @@ -862,6 +862,7 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=m CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2=m CONFIG_REGULATOR_WAVESHARE_TOUCHSCREEN=m +CONFIG_REGULATOR_EDATEC_PANEL=m CONFIG_RC_CORE=y CONFIG_BPF_LIRC_MODE2=y CONFIG_LIRC=y diff --git a/arch/arm64/configs/bcm2712_defconfig b/arch/arm64/configs/bcm2712_defconfig index d607fd38841316..593d484defdfa4 100644 --- a/arch/arm64/configs/bcm2712_defconfig +++ b/arch/arm64/configs/bcm2712_defconfig @@ -865,6 +865,7 @@ CONFIG_REGULATOR_GPIO=y CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=m CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2=m CONFIG_REGULATOR_WAVESHARE_TOUCHSCREEN=m +CONFIG_REGULATOR_EDATEC_PANEL=m CONFIG_RC_CORE=y CONFIG_BPF_LIRC_MODE2=y CONFIG_LIRC=y From 3a9df29d975004e2a4c35e5c97e31f10ce99a6b6 Mon Sep 17 00:00:00 2001 From: FrankLeeEDA Date: Thu, 4 Jun 2026 14:30:34 +0000 Subject: [PATCH 4/4] arm64: dts: overlays: add edatec 101c and 070c DSI panel overlays Add overlays for edatec 10inch (101c) and 7inch (070c) DSI panels. Update Makefile to build these new overlays and README to document their usage. Signed-off-by: FrankLeeEDA --- arch/arm/boot/dts/overlays/Makefile | 2 + arch/arm/boot/dts/overlays/README | 23 ++++ .../vc4-kms-dsi-edatec-panel-070c-overlay.dts | 119 ++++++++++++++++++ .../vc4-kms-dsi-edatec-panel-101c-overlay.dts | 116 +++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-070c-overlay.dts create mode 100644 arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-101c-overlay.dts diff --git a/arch/arm/boot/dts/overlays/Makefile b/arch/arm/boot/dts/overlays/Makefile index 261dfb885a0362..ea5a30939dca43 100644 --- a/arch/arm/boot/dts/overlays/Makefile +++ b/arch/arm/boot/dts/overlays/Makefile @@ -337,6 +337,8 @@ dtbo-$(CONFIG_ARCH_BCM2835) += \ vc4-kms-dpi-hyperpixel4sq.dtbo \ vc4-kms-dpi-panel.dtbo \ vc4-kms-dsi-7inch.dtbo \ + vc4-kms-dsi-edatec-panel-070c.dtbo \ + vc4-kms-dsi-edatec-panel-101c.dtbo \ vc4-kms-dsi-generic.dtbo \ vc4-kms-dsi-ili79600-10-1inch.dtbo \ vc4-kms-dsi-ili9881-5inch.dtbo \ diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README index ec3b9053cdf8ab..f74f49cb30fb3c 100644 --- a/arch/arm/boot/dts/overlays/README +++ b/arch/arm/boot/dts/overlays/README @@ -5791,6 +5791,29 @@ Params: sizex Touchscreen size x (default 800) the default DSI1 and i2c_csi_dsi). +Name: vc4-kms-dsi-edatec-panel-070c +Info: Enable the edatec DSI 7" screen. + support ed-dispr-070c. + support ed-dispr5-070c. + support ed-dispr4-070c. +Load: dtoverlay=vc4-kms-dsi-edatec-panel-070c,= +Params: interrupt GPIO pin for interrupt signal(default 16) + i2c1 Use i2c-1 + i2c4 Use i2c-4 (specialized for CM5) + + +Name: vc4-kms-dsi-edatec-panel-101c +Info: Enable the edatec DSI 10" screen. + support ed-dispr-101c. + support ed-dispr5-101c. + support ed-dispr4-101c. +Load: dtoverlay=vc4-kms-dsi-edatec-panel-101c,= +Params: rotation Display rotation {0,90,180,270} (default 270) + interrupt GPIO pin for interrupt signal(default 16) + i2c1 Use i2c-1 + i2c4 Use i2c-4 (specialized for CM5) + + Name: vc4-kms-dsi-generic Info: Enable a generic DSI display under KMS. Default timings are for a 840x480 RGB888 panel. diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-070c-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-070c-overlay.dts new file mode 100644 index 00000000000000..4a075a885dbe79 --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-070c-overlay.dts @@ -0,0 +1,119 @@ +/dts-v1/; +/plugin/; + +/ { + compatible = "brcm,bcm2835"; + + i2c_frag: fragment@0 { + target = <&i2c_csi_dsi>; + __overlay__ { + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + reg_display: reg_display@27 { + reg = <0x27>; + compatible = "edatec,disp-regulator"; + + gpio-controller; + #gpio-cells = <2>; + }; + + gt911: gt911@14 { + compatible = "goodix,gt911"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <>911_pins>; + + reset-gpios = <®_display 3 0>; + interrupt-parent = <&gpio>; + interrupts = <16 2>; + irq-gpios = <&gpio 16 0>; + }; + }; + }; + + fragment@1 { + target = <&dsi1>; + __overlay__ { + status = "okay"; + port { + dsi_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + + panel: panel@0 { + reg = <0>; + compatible = "panel-dsi"; + backlight = <®_display>; + + width-mm = <154>; + height-mm = <86>; + dsi-color-format = "RGB888"; + mode = "MODE_VIDEO","MODE_VIDEO_SYNC_PULSE"; + + timing: panel-timing { + clock-frequency = <41000000>; + hactive = <1024>; + hfront-porch = <40>; + hsync-len = <10>; + hback-porch = <40>; + vactive = <600>; + vfront-porch = <4>; + vsync-len = <2>; + vback-porch = <4>; + }; + + port { + panel_in: endpoint { + data-lanes = <1 2>; + remote-endpoint = <&dsi_out>; + }; + }; + }; + }; + }; + + fragment@2 { + target = <&i2c0if>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@3 { + target = <&i2c0mux>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@4 { + target = <&i2c1>; + __dormant__ { + status = "okay"; + }; + }; + + fragment@5 { + target = <&gpio>; + __overlay__ { + gt911_pins: gt911_pins { + brcm,pins = <16>; + brcm,function = <0>; + brcm,pull = <2>; + }; + }; + }; + + __overrides__ { + i2c1 = <&i2c_frag>, "target:0=",<&i2c1>, + <0>,"-2-3+4"; + i2c4 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>; + interrupt = <>911_pins>,"brcm,pins:0", + <>911>,"interrupts:0", + <>911>,"irq-gpios:4"; + }; +}; diff --git a/arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-101c-overlay.dts b/arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-101c-overlay.dts new file mode 100644 index 00000000000000..35c97c18cc64dd --- /dev/null +++ b/arch/arm/boot/dts/overlays/vc4-kms-dsi-edatec-panel-101c-overlay.dts @@ -0,0 +1,116 @@ +/dts-v1/; +/plugin/; + +#include + +/ { + compatible = "brcm,bcm2835"; + + fragment@0 { + target-path = "/"; + __overlay__ { + vdd_lcd: fixedregulator_lcd { + compatible = "regulator-fixed"; + regulator-name = "vdd_lcd"; + + gpios = <®_display 4 GPIO_ACTIVE_HIGH>; + startup-delay-us = <5000>; + enable-active-high; + }; + }; + }; + + fragment@1 { + target = <&dsi1>; + __overlay__{ + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + port { + dsi_out_port:endpoint { + remote-endpoint = <&panel_dsi_port>; + }; + }; + + ili9881c:ili9881c@0 { + compatible = "rzw,t101p136cq"; + status = "okay"; + reg = <0>; + + reset-gpios = <®_display 2 GPIO_ACTIVE_LOW>; + backlight = <®_display>; + power-supply = <&vdd_lcd>; + rotation = <270>; + + port { + panel_dsi_port: endpoint { + remote-endpoint = <&dsi_out_port>; + }; + }; + }; + }; + }; + + fragment@2 { + target = <&i2c0if>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@3 { + target = <&i2c0mux>; + __overlay__ { + status = "okay"; + }; + }; + + fragment@4 { + target = <&gpio>; + __overlay__ { + gt928_pins: gt928_pins { + brcm,pins = <16>; + brcm,function = <0>; + brcm,pull = <2>; + }; + }; + }; + + i2c_frag: fragment@5 { + target = <&i2c_csi_dsi>; + __overlay__ { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + reg_display: reg_display@27 { + compatible = "edatec,disp-regulator"; + reg = <0x27>; + gpio-controller; + #gpio-cells = <2>; + }; + + gt928:gt928@14 { + compatible = "goodix,gt928"; + reg = <0x14>; + pinctrl-names = "default"; + pinctrl-0 = <>928_pins>; + + reset-gpios = <®_display 3 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio>; + interrupts = <16 2>; + irq-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>; + }; + }; + }; + + __overrides__ { + i2c1 = <&i2c_frag>, "target:0=",<&i2c1>, + <0>, "-3-4+5"; + i2c4 = <&i2c_frag>, "target:0=",<&i2c_csi_dsi0>; + interrupt = <>928_pins>, "brcm,pins:0", + <>928>, "interrupts:0", + <>928>, "irq-gpios:4"; + rotation = <&ili9881c>, "rotation:0"; + }; +};