From: Viktar Simanenka <viteosen@gmail.com>
To: David Airlie <airlied@gmail.com>, Daniel Vetter <daniel@ffwll.ch>,
Rob Herring <robh+dt@kernel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
Conor Dooley <conor+dt@kernel.org>,
Viktar Simanenka <viteosen@gmail.com>,
dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] drm/tiny: add display driver for philips pcd8544 display controller
Date: Wed, 19 Jul 2023 12:29:03 +0300 [thread overview]
Message-ID: <20230719092903.316452-2-viteosen@gmail.com> (raw)
In-Reply-To: <20230719092903.316452-1-viteosen@gmail.com>
Support for common monochrome LCD displays based on PCD8544 (such as
Nokia 5110/3310 LCD) SPI controlled displays.
On 2023-07-18 8:35, Krzysztof Kozlowski wrote:
> > + pcd8544_dev->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
> > + if (IS_ERR(pcd8544_dev->reset))
> > + return dev_err_probe(dev, PTR_ERR(pcd8544_dev->reset), "Failed to get GPIO 'reset'\n");
> You start in reset mode? Didn't you just confure values? 1 is reset.
On this controller RESET is active LOW. I start it in normal mode.
> Drop. And run coccinelle, smatch and sparse.
Run through and fixed warnings with smatch and sparse.
Signed-off-by: Viktar Simanenka <viteosen@gmail.com>
---
drivers/gpu/drm/tiny/Kconfig | 11 +
drivers/gpu/drm/tiny/Makefile | 1 +
drivers/gpu/drm/tiny/pcd8544.c | 506 +++++++++++++++++++++++++++++++++
3 files changed, 518 insertions(+)
create mode 100644 drivers/gpu/drm/tiny/pcd8544.c
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index f6889f649bc1..10caa0818253 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -172,6 +172,17 @@ config TINYDRM_MI0283QT
DRM driver for the Multi-Inno MI0283QT display panel
If M is selected the module will be called mi0283qt.
+config TINYDRM_PCD8544
+ tristate "DRM support for PCD8544 displays"
+ depends on DRM && SPI
+ select DRM_KMS_HELPER
+ select DRM_GEM_DMA_HELPER
+ select BACKLIGHT_CLASS_DEVICE
+ help
+ DRM driver for PCD8544 (Nokia 5110/3310) 84x48 LCD displays.
+
+ If M is selected the module will be called pcd8544.
+
config TINYDRM_REPAPER
tristate "DRM support for Pervasive Displays RePaper panels (V231)"
depends on DRM && SPI
diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile
index 76dde89a044b..75bc112a02f9 100644
--- a/drivers/gpu/drm/tiny/Makefile
+++ b/drivers/gpu/drm/tiny/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o
obj-$(CONFIG_TINYDRM_ILI9341) += ili9341.o
obj-$(CONFIG_TINYDRM_ILI9486) += ili9486.o
obj-$(CONFIG_TINYDRM_MI0283QT) += mi0283qt.o
+obj-$(CONFIG_TINYDRM_PCD8544) += pcd8544.o
obj-$(CONFIG_TINYDRM_REPAPER) += repaper.o
obj-$(CONFIG_TINYDRM_ST7586) += st7586.o
obj-$(CONFIG_TINYDRM_ST7735R) += st7735r.o
diff --git a/drivers/gpu/drm/tiny/pcd8544.c b/drivers/gpu/drm/tiny/pcd8544.c
new file mode 100644
index 000000000000..5f4577d4b961
--- /dev/null
+++ b/drivers/gpu/drm/tiny/pcd8544.c
@@ -0,0 +1,506 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * DRM driver for Philips PCD8544 LCD controller/driver.
+ * Compatible with Nokia 5110/3310 84x48 LCD displays.
+ *
+ * Copyright 2023 Viktar Simanenka <viteosen@gmail.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/spi/spi.h>
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_dma_helper.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_probe_helper.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_simple_kms_helper.h>
+
+/*
+ * The display is monochrome, every bit in buffer is a pixel.
+ * Display RAM divided into 6 banks along y-axis, each bank 84 bytes along x-axis.
+ * Driver uses horizontal addressing.
+ */
+
+#define PCD8544_FUNCTIONSET 0x20
+#define PCD8544_DISPLAYCONTROL 0x08
+#define PCD8544_SETYADDR 0x40
+#define PCD8544_SETXADDR 0x80
+#define PCD8544_SETBIAS 0x10
+#define PCD8544_SETTEMPCOEF 0x04
+#define PCD8544_SETVOP 0x80
+
+#define PCD8544_EXTENDED_INSTRUCTION 0x01
+#define PCD8544_VERTICAL_ADDRESSING 0x02
+#define PCD8544_DISPLAYNORMAL 0x04
+#define PCD8544_DISPLAYINVERTED 0x05
+
+struct pcd8544_device {
+ struct drm_device drm;
+ struct drm_simple_display_pipe pipe;
+ struct drm_connector connector;
+ struct drm_display_mode mode;
+ struct spi_device *spi;
+
+ u32 width;
+ u32 height;
+ u8 *tx_buf; // Buffer used for transfer
+ size_t tx_buflen;
+
+ struct backlight_device *backlight;
+ struct gpio_desc *reset;
+ struct gpio_desc *dc;
+
+ u32 inverted;
+ u32 temperature_coeff;
+ u32 bias;
+ u32 voltage_op;
+};
+
+MODULE_PARM_DESC(inverted, "Invert colors: 1 - enable, 0 - disable");
+MODULE_PARM_DESC(temperature_coeff, "TC[1:0] Temperature coefficient: 0-3 (default: 0)");
+MODULE_PARM_DESC(bias, "BS[2:0] Bias voltage level: 0-7 (default: 4)");
+MODULE_PARM_DESC(voltage_op, "Vop[6:0] Set operation voltage: 0-127 (default: 0)");
+
+#define drm_to_dev(__dev) container_of(__dev, struct pcd8544_device, drm)
+
+static int pcd8544_spi_transfer(struct spi_device *spi, const void *buf, size_t len)
+{
+ size_t max_chunk = spi_max_transfer_size(spi);
+ struct spi_transfer tr = {
+ .bits_per_word = 8,
+ .speed_hz = 0,
+ };
+ struct spi_message m;
+ size_t chunk;
+ int ret;
+
+ max_chunk = ALIGN_DOWN(max_chunk, 2);
+
+ spi_message_init_with_transfers(&m, &tr, 1);
+
+ while (len) {
+ chunk = min(len, max_chunk);
+
+ tr.tx_buf = buf;
+ tr.len = chunk;
+ buf += chunk;
+ len -= chunk;
+
+ ret = spi_sync(spi, &m);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int pcd8544_spi_command(struct pcd8544_device *pcd8544_dev, u8 cmd)
+{
+ struct spi_device *spi = pcd8544_dev->spi;
+
+ gpiod_set_value_cansleep(pcd8544_dev->dc, 0);
+
+ return pcd8544_spi_transfer(spi, &cmd, 1);
+}
+
+static int pcd8544_spi_data(struct pcd8544_device *pcd8544_dev,
+ const void *tx_buf, size_t len)
+{
+ struct spi_device *spi = pcd8544_dev->spi;
+
+ gpiod_set_value_cansleep(pcd8544_dev->dc, 1);
+
+ return pcd8544_spi_transfer(spi, tx_buf, len);
+}
+
+static void pcd8544_screen_update(struct pcd8544_device *pcd8544_dev,
+ const u8 *buf, size_t len, u8 addr_x, u8 addr_y)
+{
+ pcd8544_spi_command(pcd8544_dev, PCD8544_SETYADDR | addr_y);
+ pcd8544_spi_command(pcd8544_dev, PCD8544_SETXADDR | addr_x);
+ pcd8544_spi_data(pcd8544_dev, buf, len);
+}
+
+static int pcd8544_fb_xrgb8888_to_mono(u8 *dst, struct drm_framebuffer *fb,
+ struct drm_rect *clip)
+{
+ struct iosys_map fb_map[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map fb_data[DRM_FORMAT_MAX_PLANES];
+ struct iosys_map buf_map;
+ u8 *buf;
+ unsigned int width = drm_rect_width(clip);
+ unsigned int height = drm_rect_height(clip);
+ unsigned int line_length = DIV_ROUND_UP(width, 8);
+ unsigned int bank_max = DIV_ROUND_UP(height, 8);
+ unsigned int x, y, bank;
+ int ret = 0;
+
+ buf = kcalloc(line_length, height, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ buf_map = (struct iosys_map)IOSYS_MAP_INIT_VADDR(buf);
+
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ goto out_free;
+
+ ret = drm_gem_fb_vmap(fb, fb_map, fb_data);
+ if (ret)
+ goto out_end_cpu_access;
+
+ drm_fb_xrgb8888_to_mono(&buf_map, &line_length, fb_data, fb, clip);
+
+ drm_gem_fb_vunmap(fb, fb_map);
+
+ for (bank = 0; bank < bank_max; bank++) {
+ for (x = 0; x < width; x++) {
+ u8 data = 0;
+
+ for (y = 0; y < 8; y++) {
+ u8 byte = buf[(8 * bank + y) * line_length + x / 8];
+ u8 bit = (byte >> (x % 8)) & 1;
+
+ data |= bit << y;
+ }
+ *dst++ = data;
+ }
+ }
+
+out_end_cpu_access:
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
+out_free:
+ kfree(buf);
+
+ return ret;
+}
+
+static void pcd8544_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect)
+{
+ struct pcd8544_device *pcd8544_dev = drm_to_dev(fb->dev);
+ int idx, ret = 0;
+
+ if (!drm_dev_enter(fb->dev, &idx))
+ return;
+
+ /* Align rect y to display bank boundaries */
+ rect->y1 = round_down(rect->y1, 8);
+ rect->y2 = min_t(unsigned int, round_up(rect->y2, 8), pcd8544_dev->width);
+
+ ret = pcd8544_fb_xrgb8888_to_mono(pcd8544_dev->tx_buf, fb, rect);
+ if (ret)
+ goto err_msg;
+
+ /* if full update */
+ if (rect->x1 == 0 && rect->x2 == pcd8544_dev->width &&
+ rect->y1 == 0 && rect->y2 == pcd8544_dev->height) {
+ pcd8544_screen_update(pcd8544_dev, pcd8544_dev->tx_buf, pcd8544_dev->tx_buflen, 0, 0);
+ } else {
+ u32 rect_width = drm_rect_width(rect);
+ u32 bank_min = rect->y1 / 8;
+ u32 bank_max = rect->y2 / 8;
+
+ for (u32 bank = bank_min; bank <= bank_max; bank++)
+ pcd8544_screen_update(pcd8544_dev, &pcd8544_dev->tx_buf[rect_width * (bank - bank_min)],
+ rect_width, rect->x1, bank);
+ }
+
+err_msg:
+ if (ret)
+ dev_err_once(fb->dev->dev, "Failed to update display %d\n", ret);
+
+ drm_dev_exit(idx);
+}
+
+static enum drm_mode_status pcd8544_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
+ const struct drm_display_mode *mode)
+{
+ struct drm_crtc *crtc = &pipe->crtc;
+ struct pcd8544_device *pcd8544_dev = drm_to_dev(crtc->dev);
+
+ return drm_crtc_helper_mode_valid_fixed(crtc, mode, &pcd8544_dev->mode);
+}
+
+static void pcd8544_pipe_enable(struct drm_simple_display_pipe *pipe,
+ struct drm_crtc_state *crtc_state,
+ struct drm_plane_state *plane_state)
+{
+ struct pcd8544_device *pcd8544_dev = drm_to_dev(pipe->crtc.dev);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_rect rect = {
+ .x1 = 0,
+ .x2 = fb->width,
+ .y1 = 0,
+ .y2 = fb->height,
+ };
+ int idx;
+
+ if (!drm_dev_enter(pipe->crtc.dev, &idx))
+ return;
+
+ drm_dbg(pipe->crtc.dev, "\n");
+
+ /* Reset display */
+ gpiod_set_value_cansleep(pcd8544_dev->reset, 0);
+ usleep_range(20, 1000);
+ gpiod_set_value_cansleep(pcd8544_dev->reset, 1);
+ msleep(120);
+
+ /* Init */
+ pcd8544_spi_command(pcd8544_dev, PCD8544_FUNCTIONSET | PCD8544_EXTENDED_INSTRUCTION);
+ pcd8544_spi_command(pcd8544_dev, PCD8544_SETBIAS | (pcd8544_dev->bias & 0x7));
+ pcd8544_spi_command(pcd8544_dev, PCD8544_SETTEMPCOEF | (pcd8544_dev->temperature_coeff & 0x3));
+ pcd8544_spi_command(pcd8544_dev, PCD8544_SETVOP | (pcd8544_dev->voltage_op & 0x7F));
+ pcd8544_spi_command(pcd8544_dev, PCD8544_FUNCTIONSET);
+ if (pcd8544_dev->inverted)
+ pcd8544_spi_command(pcd8544_dev, PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYINVERTED);
+ else
+ pcd8544_spi_command(pcd8544_dev, PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL);
+
+ pcd8544_fb_dirty(fb, &rect);
+
+ drm_dev_exit(idx);
+}
+
+static void pcd8544_pipe_disable(struct drm_simple_display_pipe *pipe)
+{
+ struct pcd8544_device *pcd8544_dev = drm_to_dev(pipe->crtc.dev);
+
+ drm_dbg(pipe->crtc.dev, "\n");
+
+ /* Clear screen */
+ memset(pcd8544_dev->tx_buf, 0, pcd8544_dev->tx_buflen);
+ pcd8544_screen_update(pcd8544_dev, pcd8544_dev->tx_buf, pcd8544_dev->tx_buflen, 0, 0);
+
+ if (pcd8544_dev->backlight)
+ backlight_disable(pcd8544_dev->backlight);
+}
+
+static void pcd8544_pipe_update(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *old_state)
+{
+ struct drm_plane_state *state = pipe->plane.state;
+ struct drm_rect rect;
+
+ if (!pipe->crtc.state->active)
+ return;
+
+ if (drm_atomic_helper_damage_merged(old_state, state, &rect))
+ pcd8544_fb_dirty(state->fb, &rect);
+}
+
+static const struct drm_simple_display_pipe_funcs pcd8544_pipe_funcs = {
+ .mode_valid = pcd8544_pipe_mode_valid,
+ .enable = pcd8544_pipe_enable,
+ .disable = pcd8544_pipe_disable,
+ .update = pcd8544_pipe_update,
+};
+
+DEFINE_DRM_GEM_DMA_FOPS(pcd8544_fops);
+
+static int pcd8544_connector_get_modes(struct drm_connector *connector)
+{
+ struct pcd8544_device *pcd8544_dev = drm_to_dev(connector->dev);
+
+ return drm_connector_helper_get_modes_fixed(connector, &pcd8544_dev->mode);
+}
+
+static const struct drm_connector_helper_funcs pcd8544_connector_hfuncs = {
+ .get_modes = pcd8544_connector_get_modes,
+};
+
+static const struct drm_connector_funcs pcd8544_connector_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_mode_config_funcs pcd8544_mode_config_funcs = {
+ .fb_create = drm_gem_fb_create_with_dirty,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static int __maybe_unused pcd8544_pm_suspend(struct device *dev)
+{
+ return drm_mode_config_helper_suspend(dev_get_drvdata(dev));
+}
+
+static int __maybe_unused pcd8544_pm_resume(struct device *dev)
+{
+ drm_mode_config_helper_resume(dev_get_drvdata(dev));
+
+ return 0;
+}
+
+static const struct dev_pm_ops pcd8544_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pcd8544_pm_suspend, pcd8544_pm_resume)
+};
+
+static const struct drm_driver pcd8544_driver = {
+ .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
+ .fops = &pcd8544_fops,
+ DRM_GEM_DMA_DRIVER_OPS_VMAP,
+ .name = "pcd8544",
+ .desc = "Philips PCD8544",
+ .date = "20230701",
+ .major = 1,
+ .minor = 0,
+};
+
+static const uint32_t pcd8544_formats[] = {
+ DRM_FORMAT_XRGB8888,
+};
+
+static struct drm_display_mode pcd8544_mode = {
+ DRM_SIMPLE_MODE(84, 48, 35, 28),
+};
+
+static const struct of_device_id pcd8544_of_match[] = {
+ { .compatible = "philips,pcd8544" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pcd8544_of_match);
+
+static const struct spi_device_id pcd8544_id[] = {
+ { "pcd8544", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, pcd8544_id);
+
+static int pcd8544_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct pcd8544_device *pcd8544_dev;
+ struct drm_device *drm;
+ int ret;
+ static const uint64_t modifiers[] = {
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_INVALID
+ };
+
+ pcd8544_dev = devm_drm_dev_alloc(dev, &pcd8544_driver, struct pcd8544_device, drm);
+ if (IS_ERR(pcd8544_dev))
+ return PTR_ERR(pcd8544_dev);
+
+ pcd8544_dev->spi = spi;
+
+ pcd8544_dev->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(pcd8544_dev->reset))
+ return dev_err_probe(dev, PTR_ERR(pcd8544_dev->reset), "Failed to get GPIO 'reset'\n");
+
+ pcd8544_dev->dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW);
+ if (IS_ERR(pcd8544_dev->dc))
+ return dev_err_probe(dev, PTR_ERR(pcd8544_dev->dc), "Failed to get GPIO 'dc'\n");
+
+ pcd8544_dev->backlight = devm_of_find_backlight(dev);
+ if (IS_ERR(pcd8544_dev->backlight))
+ return PTR_ERR(pcd8544_dev->backlight);
+
+ pcd8544_dev->inverted = device_property_read_bool(dev, "philips,inverted");
+ if (device_property_read_u32(dev, "philips,temperature-coeff", &pcd8544_dev->temperature_coeff))
+ pcd8544_dev->temperature_coeff = 0;
+ if (device_property_read_u32(dev, "philips,bias", &pcd8544_dev->bias))
+ pcd8544_dev->bias = 4;
+ if (device_property_read_u32(dev, "philips,voltage-op", &pcd8544_dev->voltage_op))
+ pcd8544_dev->voltage_op = 0;
+
+ if (!dev->coherent_dma_mask) {
+ ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_warn(dev, "Failed to set dma mask %d\n", ret);
+ return ret;
+ }
+ }
+
+ drm_mode_copy(&pcd8544_dev->mode, &pcd8544_mode);
+ pcd8544_dev->width = pcd8544_mode.hdisplay;
+ pcd8544_dev->height = pcd8544_mode.vdisplay;
+ pcd8544_dev->tx_buflen = pcd8544_dev->width * DIV_ROUND_UP(pcd8544_dev->height, 8);
+ pcd8544_dev->tx_buf = devm_kzalloc(dev, pcd8544_dev->tx_buflen, GFP_KERNEL);
+ if (!pcd8544_dev->tx_buf)
+ return -ENOMEM;
+
+ drm = &pcd8544_dev->drm;
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
+ drm_connector_helper_add(&pcd8544_dev->connector, &pcd8544_connector_hfuncs);
+ ret = drm_connector_init(drm, &pcd8544_dev->connector, &pcd8544_connector_funcs, DRM_MODE_CONNECTOR_SPI);
+ if (ret)
+ return ret;
+
+ drm->mode_config.funcs = &pcd8544_mode_config_funcs;
+ drm->mode_config.min_width = pcd8544_dev->mode.hdisplay;
+ drm->mode_config.max_width = pcd8544_dev->mode.hdisplay;
+ drm->mode_config.min_height = pcd8544_dev->mode.vdisplay;
+ drm->mode_config.max_height = pcd8544_dev->mode.vdisplay;
+
+ ret = drm_simple_display_pipe_init(drm, &pcd8544_dev->pipe, &pcd8544_pipe_funcs,
+ pcd8544_formats, ARRAY_SIZE(pcd8544_formats),
+ modifiers, &pcd8544_dev->connector);
+ if (ret)
+ return ret;
+
+ drm_plane_enable_fb_damage_clips(&pcd8544_dev->pipe.plane);
+
+ spi_set_drvdata(spi, drm);
+
+ drm_mode_config_reset(drm);
+
+ ret = drm_dev_register(drm, 0);
+ if (ret)
+ return ret;
+
+ drm_dbg(drm, "SPI speed: %uMHz\n", spi->max_speed_hz / 1000000);
+
+ drm_fbdev_generic_setup(drm, 0);
+
+ return 0;
+}
+
+static void pcd8544_remove(struct spi_device *spi)
+{
+ struct drm_device *drm = spi_get_drvdata(spi);
+
+ drm_dev_unplug(drm);
+ drm_atomic_helper_shutdown(drm);
+}
+
+static void pcd8544_shutdown(struct spi_device *spi)
+{
+ drm_atomic_helper_shutdown(spi_get_drvdata(spi));
+}
+
+static struct spi_driver pcd8544_spi_driver = {
+ .driver = {
+ .name = "pcd8544",
+ .owner = THIS_MODULE,
+ .of_match_table = pcd8544_of_match,
+ .pm = &pcd8544_pm_ops,
+ },
+ .id_table = pcd8544_id,
+ .probe = pcd8544_probe,
+ .remove = pcd8544_remove,
+ .shutdown = pcd8544_shutdown,
+};
+module_spi_driver(pcd8544_spi_driver);
+
+MODULE_DESCRIPTION("Philips PCD8544 DRM driver");
+MODULE_AUTHOR("Viktar Simanenka <viteosen@gmail.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
next prev parent reply other threads:[~2023-07-19 9:30 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-18 8:07 [PATCH] TinyDRM display driver for Philips PCD8544 display controller Viktar Simanenka
2023-07-18 8:35 ` Krzysztof Kozlowski
2023-07-19 9:29 ` [PATCH 1/2] dt-bindings: add vendor-prefixes and bindings for pcd8544 displays Viktar Simanenka
2023-07-19 9:29 ` Viktar Simanenka [this message]
2023-07-19 9:50 ` Krzysztof Kozlowski
2023-07-18 9:19 ` [PATCH] TinyDRM display driver for Philips PCD8544 display controller Rob Herring
2023-07-18 9:19 ` Rob Herring
2023-07-18 14:25 ` Randy Dunlap
-- strict thread matches above, loose matches on Subject: below --
2023-07-19 10:24 [PATCH 1/2] dt-bindings: add vendor-prefixes and bindings for pcd8544 displays Viktar Simanenka
2023-07-19 10:24 ` [PATCH 2/2] drm/tiny: add display driver for philips pcd8544 display controller Viktar Simanenka
2023-07-19 10:29 ` Krzysztof Kozlowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230719092903.316452-2-viteosen@gmail.com \
--to=viteosen@gmail.com \
--cc=airlied@gmail.com \
--cc=conor+dt@kernel.org \
--cc=daniel@ffwll.ch \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=krzysztof.kozlowski+dt@linaro.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.