From a5bde5d8fde8a8cb28e59a672d5ddc5b9c1e7656 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 5 Aug 2026 07:52:36 -0700 Subject: workqueue: skip the node_nr_active update for non-unbound workqueues apply_wqattrs_commit() updates node_nr_active->max unconditionally. wq->node_nr_active[] is only allocated for unbound workqueues, so guard the call before per-cpu workqueues start using this path. No functional change: only unbound workqueues reach apply_wqattrs_*() today. Signed-off-by: Breno Leitao Signed-off-by: Tejun Heo --- drivers/gpu/drm/sitronix/Kconfig | 80 +++ drivers/gpu/drm/sitronix/Makefile | 6 + drivers/gpu/drm/sitronix/st7571-i2c.c | 158 ++++++ drivers/gpu/drm/sitronix/st7571-spi.c | 76 +++ drivers/gpu/drm/sitronix/st7571.c | 918 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/sitronix/st7571.h | 91 ++++ drivers/gpu/drm/sitronix/st7586.c | 498 ++++++++++++++++++ drivers/gpu/drm/sitronix/st7735r.c | 378 ++++++++++++++ drivers/gpu/drm/sitronix/st7920.c | 867 ++++++++++++++++++++++++++++++++ 9 files changed, 3072 insertions(+) create mode 100644 drivers/gpu/drm/sitronix/Kconfig create mode 100644 drivers/gpu/drm/sitronix/Makefile create mode 100644 drivers/gpu/drm/sitronix/st7571-i2c.c create mode 100644 drivers/gpu/drm/sitronix/st7571-spi.c create mode 100644 drivers/gpu/drm/sitronix/st7571.c create mode 100644 drivers/gpu/drm/sitronix/st7571.h create mode 100644 drivers/gpu/drm/sitronix/st7586.c create mode 100644 drivers/gpu/drm/sitronix/st7735r.c create mode 100644 drivers/gpu/drm/sitronix/st7920.c (limited to 'drivers/gpu/drm/sitronix') diff --git a/drivers/gpu/drm/sitronix/Kconfig b/drivers/gpu/drm/sitronix/Kconfig new file mode 100644 index 000000000..41a428ef8 --- /dev/null +++ b/drivers/gpu/drm/sitronix/Kconfig @@ -0,0 +1,80 @@ +config DRM_ST7571 + tristate "DRM support for Sitronix ST7567/ST7571 display panels" + depends on DRM && MMU + select DRM_CLIENT_SELECTION + select DRM_GEM_SHMEM_HELPER + select DRM_KMS_HELPER + select VIDEOMODE_HELPERS + help + Sitronix ST7571 is a driver and controller for 4-level gray + scale and monochrome dot matrix LCD panels. + + DRM driver for Sitronix ST7567/ST7571 panels. + This is only the core driver, a driver for the appropriate bus + transport in your chip also must be selected. + + if M is selected the module will be called st7571. + +config DRM_ST7571_I2C + tristate "DRM support for Sitronix ST7567/ST7571 display panels (I2C)" + depends on DRM_ST7571 && I2C + select REGMAP + help + Sitronix ST7571 is a driver and controller for 4-level gray + scale and monochrome dot matrix LCD panels. + + DRM driver for Sitronix ST7565/ST7571 panels connected via I2C bus. + + if M is selected the module will be called st7571-i2c. + +config DRM_ST7571_SPI + tristate "DRM support for Sitronix ST7567/ST7571 display panels (SPI)" + depends on DRM_ST7571 && SPI + select REGMAP_SPI + help + Sitronix ST7571 is a driver and controller for 4-level gray + scale and monochrome dot matrix LCD panels. + + DRM driver for Sitronix ST7565/ST7571 panels connected via SPI bus. + + if M is selected the module will be called st7571-spi. + +config DRM_ST7586 + tristate "DRM support for Sitronix ST7586 display panels" + depends on DRM && SPI + select DRM_CLIENT_SELECTION + select DRM_KMS_HELPER + select DRM_GEM_DMA_HELPER + select DRM_MIPI_DBI + help + DRM driver for the following Sitronix ST7586 panels: + * LEGO MINDSTORMS EV3 + + If M is selected the module will be called st7586. + +config DRM_ST7735R + tristate "DRM support for Sitronix ST7715R/ST7735R display panels" + depends on DRM && SPI + select DRM_CLIENT_SELECTION + select DRM_KMS_HELPER + select DRM_GEM_DMA_HELPER + select DRM_MIPI_DBI + select BACKLIGHT_CLASS_DEVICE + help + DRM driver for Sitronix ST7715R/ST7735R with one of the following + LCDs: + * Jianda JD-T18003-T01 1.8" 128x160 TFT + * Okaya RH128128T 1.44" 128x128 TFT + + If M is selected the module will be called st7735r. + +config DRM_ST7920 + tristate "DRM support for Sitronix ST7920 LCD displays" + depends on DRM && SPI && MMU + select DRM_GEM_SHMEM_HELPER + select DRM_KMS_HELPER + select REGMAP_SPI + help + DRM driver for the ST7920 Sitronix LCD controllers. + + If M is selected the module will be called st7920. diff --git a/drivers/gpu/drm/sitronix/Makefile b/drivers/gpu/drm/sitronix/Makefile new file mode 100644 index 000000000..d03beff37 --- /dev/null +++ b/drivers/gpu/drm/sitronix/Makefile @@ -0,0 +1,6 @@ +obj-$(CONFIG_DRM_ST7571) += st7571.o +obj-$(CONFIG_DRM_ST7571_I2C) += st7571-i2c.o +obj-$(CONFIG_DRM_ST7571_SPI) += st7571-spi.o +obj-$(CONFIG_DRM_ST7586) += st7586.o +obj-$(CONFIG_DRM_ST7735R) += st7735r.o +obj-$(CONFIG_DRM_ST7920) += st7920.o diff --git a/drivers/gpu/drm/sitronix/st7571-i2c.c b/drivers/gpu/drm/sitronix/st7571-i2c.c new file mode 100644 index 000000000..44bc94be3 --- /dev/null +++ b/drivers/gpu/drm/sitronix/st7571-i2c.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Sitronix ST7571 connected via I2C bus. + * + * Copyright (C) 2025 Marcus Folkesson + */ + +#include +#include +#include + +#include "st7571.h" + +struct st7571_i2c_transport { + struct i2c_client *client; + + /* + * Depending on the hardware design, the acknowledge signal may be hard to + * recognize as a valid logic "0" level. + * Therefor, ignore NAK if possible to stay compatible with most hardware designs + * and off-the-shelf panels out there. + * + * From section 6.4 MICROPOCESSOR INTERFACE section in the datasheet: + * + * "By connecting SDA_OUT to SDA_IN externally, the SDA line becomes fully + * I2C interface compatible. + * Separating acknowledge-output from serial data + * input is advantageous for chip-on-glass (COG) applications. In COG + * applications, the ITO resistance and the pull-up resistor will form a + * voltage divider, which affects acknowledge-signal level. Larger ITO + * resistance will raise the acknowledged-signal level and system cannot + * recognize this level as a valid logic “0” level. By separating SDA_IN from + * SDA_OUT, the IC can be used in a mode that ignores the acknowledge-bit. + * For applications which check acknowledge-bit, it is necessary to minimize + * the ITO resistance of the SDA_OUT trace to guarantee a valid low level." + * + */ + bool ignore_nak; +}; + +static int st7571_i2c_regmap_write(void *context, const void *data, size_t count) +{ + struct st7571_i2c_transport *t = context; + int ret; + + struct i2c_msg msg = { + .addr = t->client->addr, + .flags = t->ignore_nak ? I2C_M_IGNORE_NAK : 0, + .len = count, + .buf = (u8 *)data + }; + + ret = i2c_transfer(t->client->adapter, &msg, 1); + + /* + * Unfortunately, there is no way to check if the transfer failed because of + * a NAK or something else as I2C bus drivers use different return values for NAK. + * + * However, if the transfer fails and ignore_nak is set, we know it is an error. + */ + if (ret < 0 && t->ignore_nak) + return ret; + + return 0; +} + +/* The st7571 driver does not read registers but regmap expects a .read */ +static int st7571_i2c_regmap_read(void *context, const void *reg_buf, + size_t reg_size, void *val_buf, size_t val_size) +{ + return -EOPNOTSUPP; +} + +static const struct regmap_bus st7571_i2c_regmap_bus = { + .read = st7571_i2c_regmap_read, + .write = st7571_i2c_regmap_write, +}; + +static const struct regmap_config st7571_i2c_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .use_single_write = true, +}; + +static int st7571_i2c_probe(struct i2c_client *client) +{ + struct st7571_device *st7571; + struct st7571_i2c_transport *t; + struct regmap *regmap; + + t = devm_kzalloc(&client->dev, sizeof(*t), GFP_KERNEL); + if (!t) + return -ENOMEM; + + t->client = client; + + /* + * The hardware design could make it hard to detect a NAK on the I2C bus. + * If the adapter does not support protocol mangling do + * not set the I2C_M_IGNORE_NAK flag at the expense * of possible + * cruft in the logs. + */ + if (i2c_check_functionality(client->adapter, I2C_FUNC_PROTOCOL_MANGLING)) + t->ignore_nak = true; + + regmap = devm_regmap_init(&client->dev, &st7571_i2c_regmap_bus, + t, &st7571_i2c_regmap_config); + if (IS_ERR(regmap)) { + return dev_err_probe(&client->dev, PTR_ERR(regmap), + "Failed to initialize regmap\n"); + } + + st7571 = st7571_probe(&client->dev, regmap); + if (IS_ERR(st7571)) + return dev_err_probe(&client->dev, PTR_ERR(st7571), + "Failed to initialize regmap\n"); + + i2c_set_clientdata(client, st7571); + return 0; +} + +static void st7571_i2c_remove(struct i2c_client *client) +{ + struct st7571_device *st7571 = i2c_get_clientdata(client); + + st7571_remove(st7571); +} + +static const struct of_device_id st7571_of_match[] = { + { .compatible = "sitronix,st7567", .data = &st7567_config }, + { .compatible = "sitronix,st7571", .data = &st7571_config }, + {}, +}; +MODULE_DEVICE_TABLE(of, st7571_of_match); + +static const struct i2c_device_id st7571_id[] = { + { "st7567", 0 }, + { "st7571", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, st7571_id); + +static struct i2c_driver st7571_i2c_driver = { + .driver = { + .name = "st7571-i2c", + .of_match_table = st7571_of_match, + }, + .probe = st7571_i2c_probe, + .remove = st7571_i2c_remove, + .id_table = st7571_id, +}; + +module_i2c_driver(st7571_i2c_driver); + +MODULE_AUTHOR("Marcus Folkesson "); +MODULE_DESCRIPTION("DRM Driver for Sitronix ST7571 LCD controller (I2C)"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("DRM_ST7571"); diff --git a/drivers/gpu/drm/sitronix/st7571-spi.c b/drivers/gpu/drm/sitronix/st7571-spi.c new file mode 100644 index 000000000..0206e9162 --- /dev/null +++ b/drivers/gpu/drm/sitronix/st7571-spi.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Sitronix ST7571 connected via SPI bus. + * + * Copyright (C) 2025 Marcus Folkesson + */ + +#include +#include +#include + +#include "st7571.h" + +static const struct regmap_config st7571_spi_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .can_multi_write = true, +}; + +static int st7571_spi_probe(struct spi_device *spi) +{ + struct st7571_device *st7571; + struct regmap *regmap; + + regmap = devm_regmap_init_spi(spi, &st7571_spi_regmap_config); + if (IS_ERR(regmap)) { + return dev_err_probe(&spi->dev, PTR_ERR(regmap), + "Failed to initialize regmap\n"); + } + + st7571 = st7571_probe(&spi->dev, regmap); + if (IS_ERR(st7571)) + return dev_err_probe(&spi->dev, PTR_ERR(st7571), + "Failed to initialize regmap\n"); + + spi_set_drvdata(spi, st7571); + return 0; +} + +static void st7571_spi_remove(struct spi_device *spi) +{ + struct st7571_device *st7571 = spi_get_drvdata(spi); + + st7571_remove(st7571); +} + +static const struct of_device_id st7571_of_match[] = { + { .compatible = "sitronix,st7567", .data = &st7567_config }, + { .compatible = "sitronix,st7571", .data = &st7571_config }, + {}, +}; +MODULE_DEVICE_TABLE(of, st7571_of_match); + +static const struct spi_device_id st7571_spi_id[] = { + { "st7567", 0 }, + { "st7571", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, st7571_spi_id); + +static struct spi_driver st7571_spi_driver = { + .driver = { + .name = "st7571-spi", + .of_match_table = st7571_of_match, + }, + .probe = st7571_spi_probe, + .remove = st7571_spi_remove, + .id_table = st7571_spi_id, +}; + +module_spi_driver(st7571_spi_driver); + +MODULE_AUTHOR("Marcus Folkesson "); +MODULE_DESCRIPTION("DRM Driver for Sitronix ST7571 LCD controller (SPI)"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS("DRM_ST7571"); diff --git a/drivers/gpu/drm/sitronix/st7571.c b/drivers/gpu/drm/sitronix/st7571.c new file mode 100644 index 000000000..20954c33e --- /dev/null +++ b/drivers/gpu/drm/sitronix/st7571.c @@ -0,0 +1,918 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Driver for Sitronix ST7571, a 4 level gray scale dot matrix LCD controller + * + * Copyright (C) 2025 Marcus Folkesson + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include