Message ID | 1513884233-31540-4-git-send-email-david@lechnology.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 12/21/2017 01:23 PM, David Lechner wrote: > This adds a new driver for Sitronix ST7735R display panels. > > This has been tested using an Adafruit 1.8" TFT. > > Signed-off-by: David Lechner <david@lechnology.com> > --- <snip> > + mipi_dbi_command(mipi, ST7735R_GAMCTRP1, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, > + 0x28, 0x20, 0x22, 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, > + 0x02, 0x10); > + mipi_dbi_command(mipi, ST7735R_GAMCTRN1, 0x0f, 0x1b, 0x0f, 0x17, 0x33, > + 0x2c, 0x29, 0x2e, 0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, > + 0x03, 0x10); By the way, how do you know what is the "right" gamma curve? I think I copied this from the generic st7735r driver in fbtft, but I noticed that there is also a different curve for the Adafruit 1.8" display in fbtft. I'm wondering if I should have used that one instead. I can't really tell a difference looking at the display.
Den 21.12.2017 20.23, skrev David Lechner: > This adds a new driver for Sitronix ST7735R display panels. > > This has been tested using an Adafruit 1.8" TFT. > > Signed-off-by: David Lechner <david@lechnology.com> > --- > > v3 changes: > * Changed compatible string > * use SPDX license header > * Renamed mode struct to use panel name instead of controller name > > v2 changes: > * Change delay from 10ms to 20ms to avoid checkpatch warning > * Use mipi_dbi_pipe_enable()/mipi_dbi_pipe_disable() to reduce duplicated code > * Rebase on drm-misc-next (tinydrm_lastclose => drm_fb_helper_lastclose) > * Use mipi_dbi_debugfs_init > * Add mipi->read_commands = NULL; since this display is write-only <snip> > diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c > new file mode 100644 > index 0000000..0b05b2c > --- /dev/null > +++ b/drivers/gpu/drm/tinydrm/st7735r.c > @@ -0,0 +1,215 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * DRM driver for Sitronix ST7735R panels > + * > + * Copyright 2017 David Lechner <david@lechnology.com> > + */ > + > +#include <linux/delay.h> > +#include <linux/dma-buf.h> > +#include <linux/gpio/consumer.h> > +#include <linux/module.h> > +#include <linux/property.h> > +#include <linux/spi/spi.h> > +#include <video/mipi_display.h> > + > +#include <drm/drm_fb_helper.h> > +#include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/tinydrm/mipi-dbi.h> > +#include <drm/tinydrm/tinydrm-helpers.h> > + > +#define ST7735R_FRMCTR1 0xb1 > +#define ST7735R_FRMCTR2 0xb2 > +#define ST7735R_FRMCTR3 0xb3 > +#define ST7735R_INVCTR 0xb4 > +#define ST7735R_PWCTR1 0xc0 > +#define ST7735R_PWCTR2 0xc1 > +#define ST7735R_PWCTR3 0xc2 > +#define ST7735R_PWCTR4 0xc3 > +#define ST7735R_PWCTR5 0xc4 > +#define ST7735R_VMCTR1 0xc5 > +#define ST7735R_GAMCTRP1 0xe0 > +#define ST7735R_GAMCTRN1 0xe1 > + > +#define ST7735R_MY BIT(7) > +#define ST7735R_MX BIT(6) > +#define ST7735R_MV BIT(5) > + > +static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe, > + struct drm_crtc_state *crtc_state) This is confusing, you name the mode after the panel, but not the enable function which has an initialization sequence that is also panel specific. With .enable function named after the panel (and *_pipe_funcs): Reviewed-by: Noralf Trønnes <noralf@tronnes.org> > +{ > + struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); > + struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); > + struct device *dev = tdev->drm->dev; > + int ret; > + u8 addr_mode; > + > + DRM_DEBUG_KMS("\n"); > + > + mipi_dbi_hw_reset(mipi); > + > + ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET); > + if (ret) { > + DRM_DEV_ERROR(dev, "Error sending command %d\n", ret); > + return; > + } > + > + msleep(150); > + > + mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); > + msleep(500); > + > + mipi_dbi_command(mipi, ST7735R_FRMCTR1, 0x01, 0x2c, 0x2d); > + mipi_dbi_command(mipi, ST7735R_FRMCTR2, 0x01, 0x2c, 0x2d); > + mipi_dbi_command(mipi, ST7735R_FRMCTR3, 0x01, 0x2c, 0x2d, 0x01, 0x2c, > + 0x2d); > + mipi_dbi_command(mipi, ST7735R_INVCTR, 0x07); > + mipi_dbi_command(mipi, ST7735R_PWCTR1, 0xa2, 0x02, 0x84); > + mipi_dbi_command(mipi, ST7735R_PWCTR2, 0xc5); > + mipi_dbi_command(mipi, ST7735R_PWCTR3, 0x0a, 0x00); > + mipi_dbi_command(mipi, ST7735R_PWCTR4, 0x8a, 0x2a); > + mipi_dbi_command(mipi, ST7735R_PWCTR5, 0x8a, 0xee); > + mipi_dbi_command(mipi, ST7735R_VMCTR1, 0x0e); > + mipi_dbi_command(mipi, MIPI_DCS_EXIT_INVERT_MODE); > + switch (mipi->rotation) { > + default: > + addr_mode = ST7735R_MX | ST7735R_MY; > + break; > + case 90: > + addr_mode = ST7735R_MX | ST7735R_MV; > + break; > + case 180: > + addr_mode = 0; > + break; > + case 270: > + addr_mode = ST7735R_MY | ST7735R_MV; > + break; > + } > + mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); > + mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, > + MIPI_DCS_PIXEL_FMT_16BIT); > + mipi_dbi_command(mipi, ST7735R_GAMCTRP1, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, > + 0x28, 0x20, 0x22, 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, > + 0x02, 0x10); > + mipi_dbi_command(mipi, ST7735R_GAMCTRN1, 0x0f, 0x1b, 0x0f, 0x17, 0x33, > + 0x2c, 0x29, 0x2e, 0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, > + 0x03, 0x10); > + mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); > + > + msleep(100); > + > + mipi_dbi_command(mipi, MIPI_DCS_ENTER_NORMAL_MODE); > + > + msleep(20); > + > + mipi_dbi_pipe_enable(pipe, crtc_state); > +} > + > +static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = { > + .enable = st7735r_pipe_enable, > + .disable = mipi_dbi_pipe_disable, > + .update = tinydrm_display_pipe_update, > + .prepare_fb = tinydrm_display_pipe_prepare_fb, > +}; > + > +static const struct drm_display_mode jd_t18003_t01_mode = { > + TINYDRM_MODE(128, 160, 28, 35), > +}; > + > +DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops); > + > +static struct drm_driver st7735r_driver = { > + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > + DRIVER_ATOMIC, > + .fops = &st7735r_fops, > + TINYDRM_GEM_DRIVER_OPS, > + .lastclose = drm_fb_helper_lastclose, > + .debugfs_init = mipi_dbi_debugfs_init, > + .name = "st7735r", > + .desc = "Sitronix ST7735R", > + .date = "20171128", > + .major = 1, > + .minor = 0, > +}; > + > +static const struct of_device_id st7735r_of_match[] = { > + { .compatible = "jianda,jd-t18003-t01" }, > + {}, > +}; > +MODULE_DEVICE_TABLE(of, st7735r_of_match); > + > +static const struct spi_device_id st7735r_id[] = { > + { "jd-t18003-t01", 0 }, > + { }, > +}; > +MODULE_DEVICE_TABLE(spi, st7735r_id); > + > +static int st7735r_probe(struct spi_device *spi) > +{ > + struct device *dev = &spi->dev; > + struct mipi_dbi *mipi; > + struct gpio_desc *dc; > + u32 rotation = 0; > + int ret; > + > + mipi = devm_kzalloc(dev, sizeof(*mipi), GFP_KERNEL); > + if (!mipi) > + return -ENOMEM; > + > + mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); > + if (IS_ERR(mipi->reset)) { > + DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); > + return PTR_ERR(mipi->reset); > + } > + > + dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); > + if (IS_ERR(dc)) { > + DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); > + return PTR_ERR(dc); > + } > + > + mipi->backlight = tinydrm_of_find_backlight(dev); > + if (IS_ERR(mipi->backlight)) > + return PTR_ERR(mipi->backlight); > + > + device_property_read_u32(dev, "rotation", &rotation); > + > + ret = mipi_dbi_spi_init(spi, mipi, dc); > + if (ret) > + return ret; > + > + /* Cannot read from Adafruit 1.8" display via SPI */ > + mipi->read_commands = NULL; > + > + ret = mipi_dbi_init(&spi->dev, mipi, &st7735r_pipe_funcs, > + &st7735r_driver, &jd_t18003_t01_mode, rotation); > + if (ret) > + return ret; > + > + spi_set_drvdata(spi, mipi); > + > + return devm_tinydrm_register(&mipi->tinydrm); > +} > + > +static void st7735r_shutdown(struct spi_device *spi) > +{ > + struct mipi_dbi *mipi = spi_get_drvdata(spi); > + > + tinydrm_shutdown(&mipi->tinydrm); > +} > + > +static struct spi_driver st7735r_spi_driver = { > + .driver = { > + .name = "st7735r", > + .owner = THIS_MODULE, > + .of_match_table = st7735r_of_match, > + }, > + .id_table = st7735r_id, > + .probe = st7735r_probe, > + .shutdown = st7735r_shutdown, > +}; > +module_spi_driver(st7735r_spi_driver); > + > +MODULE_DESCRIPTION("Sitronix ST7735R DRM driver"); > +MODULE_AUTHOR("David Lechner <david@lechnology.com>"); > +MODULE_LICENSE("GPL");
Den 21.12.2017 20.35, skrev David Lechner: > On 12/21/2017 01:23 PM, David Lechner wrote: >> This adds a new driver for Sitronix ST7735R display panels. >> >> This has been tested using an Adafruit 1.8" TFT. >> >> Signed-off-by: David Lechner <david@lechnology.com> >> --- > > <snip> > >> + mipi_dbi_command(mipi, ST7735R_GAMCTRP1, 0x0f, 0x1a, 0x0f, 0x18, >> 0x2f, >> + 0x28, 0x20, 0x22, 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, >> + 0x02, 0x10); >> + mipi_dbi_command(mipi, ST7735R_GAMCTRN1, 0x0f, 0x1b, 0x0f, 0x17, >> 0x33, >> + 0x2c, 0x29, 0x2e, 0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, >> + 0x03, 0x10); > By the way, how do you know what is the "right" gamma curve? I think I > copied this from the generic st7735r driver in fbtft, but I noticed > that there is also a different curve for the Adafruit 1.8" display in > fbtft. I'm wondering if I should have used that one instead. I can't > really tell a difference looking at the display. From what I can tell this is the curve used by the Arduino library: https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/Adafruit_ST7735.cpp static const uint8_t PROGMEM Rcmd3[] = { // Init for 7735R, part 3 (red or green tab) 4, // 4 commands in list: ST7735_GMCTRP1, 16 , // 1: Magical unicorn dust, 16 args, no delay: 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, ST7735_GMCTRN1, 16 , // 2: Sparkles and rainbows, 16 args, no delay: 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, void Adafruit_ST7735::initR(uint8_t options) { commonInit(Rcmd1); ... commandList(Rcmd3); Noralf.
diff --git a/MAINTAINERS b/MAINTAINERS index 91268cb..95e98e2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4556,6 +4556,12 @@ S: Maintained F: drivers/gpu/drm/tinydrm/st7586.c F: Documentation/devicetree/bindings/display/st7586.txt +DRM DRIVER FOR SITRONIX ST7735R PANELS +M: David Lechner <david@lechnology.com> +S: Maintained +F: drivers/gpu/drm/tinydrm/st7735r.c +F: Documentation/devicetree/bindings/display/st7735r.txt + DRM DRIVER FOR TDFX VIDEO CARDS S: Orphan / Obsolete F: drivers/gpu/drm/tdfx/ diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig index 90c5bd5..b0e567d 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tinydrm/Kconfig @@ -52,3 +52,13 @@ config TINYDRM_ST7586 * LEGO MINDSTORMS EV3 If M is selected the module will be called st7586. + +config TINYDRM_ST7735R + tristate "DRM support for Sitronix ST7735R display panels" + depends on DRM_TINYDRM && SPI + select TINYDRM_MIPI_DBI + help + DRM driver Sitronix ST7735R with one of the following LCDs: + * JD-T18003-T01 1.8" 128x160 TFT + + If M is selected the module will be called st7735r. diff --git a/drivers/gpu/drm/tinydrm/Makefile b/drivers/gpu/drm/tinydrm/Makefile index 8aeee53..49a1119 100644 --- a/drivers/gpu/drm/tinydrm/Makefile +++ b/drivers/gpu/drm/tinydrm/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o obj-$(CONFIG_TINYDRM_MI0283QT) += mi0283qt.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/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c new file mode 100644 index 0000000..0b05b2c --- /dev/null +++ b/drivers/gpu/drm/tinydrm/st7735r.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DRM driver for Sitronix ST7735R panels + * + * Copyright 2017 David Lechner <david@lechnology.com> + */ + +#include <linux/delay.h> +#include <linux/dma-buf.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/property.h> +#include <linux/spi/spi.h> +#include <video/mipi_display.h> + +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/tinydrm/mipi-dbi.h> +#include <drm/tinydrm/tinydrm-helpers.h> + +#define ST7735R_FRMCTR1 0xb1 +#define ST7735R_FRMCTR2 0xb2 +#define ST7735R_FRMCTR3 0xb3 +#define ST7735R_INVCTR 0xb4 +#define ST7735R_PWCTR1 0xc0 +#define ST7735R_PWCTR2 0xc1 +#define ST7735R_PWCTR3 0xc2 +#define ST7735R_PWCTR4 0xc3 +#define ST7735R_PWCTR5 0xc4 +#define ST7735R_VMCTR1 0xc5 +#define ST7735R_GAMCTRP1 0xe0 +#define ST7735R_GAMCTRN1 0xe1 + +#define ST7735R_MY BIT(7) +#define ST7735R_MX BIT(6) +#define ST7735R_MV BIT(5) + +static void st7735r_pipe_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state) +{ + struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); + struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); + struct device *dev = tdev->drm->dev; + int ret; + u8 addr_mode; + + DRM_DEBUG_KMS("\n"); + + mipi_dbi_hw_reset(mipi); + + ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET); + if (ret) { + DRM_DEV_ERROR(dev, "Error sending command %d\n", ret); + return; + } + + msleep(150); + + mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); + msleep(500); + + mipi_dbi_command(mipi, ST7735R_FRMCTR1, 0x01, 0x2c, 0x2d); + mipi_dbi_command(mipi, ST7735R_FRMCTR2, 0x01, 0x2c, 0x2d); + mipi_dbi_command(mipi, ST7735R_FRMCTR3, 0x01, 0x2c, 0x2d, 0x01, 0x2c, + 0x2d); + mipi_dbi_command(mipi, ST7735R_INVCTR, 0x07); + mipi_dbi_command(mipi, ST7735R_PWCTR1, 0xa2, 0x02, 0x84); + mipi_dbi_command(mipi, ST7735R_PWCTR2, 0xc5); + mipi_dbi_command(mipi, ST7735R_PWCTR3, 0x0a, 0x00); + mipi_dbi_command(mipi, ST7735R_PWCTR4, 0x8a, 0x2a); + mipi_dbi_command(mipi, ST7735R_PWCTR5, 0x8a, 0xee); + mipi_dbi_command(mipi, ST7735R_VMCTR1, 0x0e); + mipi_dbi_command(mipi, MIPI_DCS_EXIT_INVERT_MODE); + switch (mipi->rotation) { + default: + addr_mode = ST7735R_MX | ST7735R_MY; + break; + case 90: + addr_mode = ST7735R_MX | ST7735R_MV; + break; + case 180: + addr_mode = 0; + break; + case 270: + addr_mode = ST7735R_MY | ST7735R_MV; + break; + } + mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, + MIPI_DCS_PIXEL_FMT_16BIT); + mipi_dbi_command(mipi, ST7735R_GAMCTRP1, 0x0f, 0x1a, 0x0f, 0x18, 0x2f, + 0x28, 0x20, 0x22, 0x1f, 0x1b, 0x23, 0x37, 0x00, 0x07, + 0x02, 0x10); + mipi_dbi_command(mipi, ST7735R_GAMCTRN1, 0x0f, 0x1b, 0x0f, 0x17, 0x33, + 0x2c, 0x29, 0x2e, 0x30, 0x30, 0x39, 0x3f, 0x00, 0x07, + 0x03, 0x10); + mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); + + msleep(100); + + mipi_dbi_command(mipi, MIPI_DCS_ENTER_NORMAL_MODE); + + msleep(20); + + mipi_dbi_pipe_enable(pipe, crtc_state); +} + +static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = { + .enable = st7735r_pipe_enable, + .disable = mipi_dbi_pipe_disable, + .update = tinydrm_display_pipe_update, + .prepare_fb = tinydrm_display_pipe_prepare_fb, +}; + +static const struct drm_display_mode jd_t18003_t01_mode = { + TINYDRM_MODE(128, 160, 28, 35), +}; + +DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops); + +static struct drm_driver st7735r_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | + DRIVER_ATOMIC, + .fops = &st7735r_fops, + TINYDRM_GEM_DRIVER_OPS, + .lastclose = drm_fb_helper_lastclose, + .debugfs_init = mipi_dbi_debugfs_init, + .name = "st7735r", + .desc = "Sitronix ST7735R", + .date = "20171128", + .major = 1, + .minor = 0, +}; + +static const struct of_device_id st7735r_of_match[] = { + { .compatible = "jianda,jd-t18003-t01" }, + {}, +}; +MODULE_DEVICE_TABLE(of, st7735r_of_match); + +static const struct spi_device_id st7735r_id[] = { + { "jd-t18003-t01", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, st7735r_id); + +static int st7735r_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct mipi_dbi *mipi; + struct gpio_desc *dc; + u32 rotation = 0; + int ret; + + mipi = devm_kzalloc(dev, sizeof(*mipi), GFP_KERNEL); + if (!mipi) + return -ENOMEM; + + mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(mipi->reset)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); + return PTR_ERR(mipi->reset); + } + + dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); + if (IS_ERR(dc)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); + return PTR_ERR(dc); + } + + mipi->backlight = tinydrm_of_find_backlight(dev); + if (IS_ERR(mipi->backlight)) + return PTR_ERR(mipi->backlight); + + device_property_read_u32(dev, "rotation", &rotation); + + ret = mipi_dbi_spi_init(spi, mipi, dc); + if (ret) + return ret; + + /* Cannot read from Adafruit 1.8" display via SPI */ + mipi->read_commands = NULL; + + ret = mipi_dbi_init(&spi->dev, mipi, &st7735r_pipe_funcs, + &st7735r_driver, &jd_t18003_t01_mode, rotation); + if (ret) + return ret; + + spi_set_drvdata(spi, mipi); + + return devm_tinydrm_register(&mipi->tinydrm); +} + +static void st7735r_shutdown(struct spi_device *spi) +{ + struct mipi_dbi *mipi = spi_get_drvdata(spi); + + tinydrm_shutdown(&mipi->tinydrm); +} + +static struct spi_driver st7735r_spi_driver = { + .driver = { + .name = "st7735r", + .owner = THIS_MODULE, + .of_match_table = st7735r_of_match, + }, + .id_table = st7735r_id, + .probe = st7735r_probe, + .shutdown = st7735r_shutdown, +}; +module_spi_driver(st7735r_spi_driver); + +MODULE_DESCRIPTION("Sitronix ST7735R DRM driver"); +MODULE_AUTHOR("David Lechner <david@lechnology.com>"); +MODULE_LICENSE("GPL");
This adds a new driver for Sitronix ST7735R display panels. This has been tested using an Adafruit 1.8" TFT. Signed-off-by: David Lechner <david@lechnology.com> --- v3 changes: * Changed compatible string * use SPDX license header * Renamed mode struct to use panel name instead of controller name v2 changes: * Change delay from 10ms to 20ms to avoid checkpatch warning * Use mipi_dbi_pipe_enable()/mipi_dbi_pipe_disable() to reduce duplicated code * Rebase on drm-misc-next (tinydrm_lastclose => drm_fb_helper_lastclose) * Use mipi_dbi_debugfs_init * Add mipi->read_commands = NULL; since this display is write-only MAINTAINERS | 6 ++ drivers/gpu/drm/tinydrm/Kconfig | 10 ++ drivers/gpu/drm/tinydrm/Makefile | 1 + drivers/gpu/drm/tinydrm/st7735r.c | 215 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 drivers/gpu/drm/tinydrm/st7735r.c