From: Mikhail Durnev mikhail_durnev@mentor.com
Hi All,
This patch series is aiming at extending the mipi-dbi bus driver to support Intel 8080 type parallel bus (Type B) over GPIO and adding a new driver for ILI9341 display panels with 8- or 16-bit parallel interface.
It was tested with the MRB2801 display module [1] that had a connector compatible with the ALIENTEK STM32 development board. The module was connected to Raspberry Pi 3 via GPIO pins.
The parallel bus is implemented partially. It supports only write operations from the host to the display. Read operations would require switching GPIO mode between input and output back and forth. But this implementation is very simple, and GPIO mode can be set for all used pins to output once at initialization. The RD pin of the display has to always receive the logic high signal to make sure the data bus pins from the dislay side are always in the high impedance state. Otherwise the display module as well as the GPIO controller of the host can be damaged. To be on the safe side I recommend using protective resistors for all GPIO pins conneced to DB pins of the display. Resistors of 10 kOhms are just fine for RPi 3. The WR and DC pins may not work well with 10K resistors. Although there is no need to protect them, you can try using 1K resistors if you want.
Bit banging is used to transmit data over the parallel bus from host to display. There are two numbers that contol timings. They should be defined in the device tree via the wr-up-down-delays property. The first number is related to the write control pulse duration, and the second number is related to the write cycle duration. For ILI9341, the write pulse cannot be shorter than 15 ns, and the write duration cannot be shorter than 66 ns. Delays of 10 and 51 ns respectively allow to meet the specifications on RPi 3. Faster machines may need values closer to 15 and 66.
[1] http://www.lcdwiki.com/2.8inch_16BIT_Module_ILI9341_SKU:MRB2801
Signed-off-by: Mikhail Durnev mikhail_durnev@mentor.com
v1 -> v2: - Moved the definition of mipi_dbi_machine_little_endian() out of the "#if IS_ENABLED(CONFIG_SPI)" clause. That static function is used in mipi_dbi_gpio_init which does not need CONFIG_SPI enabled
v0 -> v1: - Rebased on v5.10-rc6 - Replaced "dbi->spi = 0;" with "dbi->spi = NULL;" in mipi_dbi_gpio_init
v0: - Based on branch rpi-5.10.y - Tested on Raspberry Pi 3 Model B V 1.2
Mikhail Durnev (3): drm/mipi-dbi: Add support for Type B drm/tiny: Add driver for ili9341 with parallel bus dt-bindings: panel: Add bindings for MRB2801
.../devicetree/bindings/display/ronbo,mrb2801.txt | 42 +++ drivers/gpu/drm/drm_mipi_dbi.c | 134 +++++++++- drivers/gpu/drm/tiny/Kconfig | 13 + drivers/gpu/drm/tiny/Makefile | 1 + drivers/gpu/drm/tiny/ili9341_gpio.c | 290 +++++++++++++++++++++ include/drm/drm_mipi_dbi.h | 30 ++- 6 files changed, 499 insertions(+), 11 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/ronbo,mrb2801.txt create mode 100644 drivers/gpu/drm/tiny/ili9341_gpio.c
From: Mikhail Durnev mikhail_durnev@mentor.com
Intel 8080 type (Type B) parallel bus over GPIO.
The parallel bus is implemented partially. It supports only write operations from the host to the display. Read operations would require switching GPIO mode between input and output back and forth. But this implementation is very simple, and GPIO mode can be set for all used pins to output once at initialization.
It is enough to support only write operations to initialize displays and output video data. The bus driver returns EOPNOTSUPP for all read operations requested through a display driver.
Bit banging is used to transmit data over the parallel bus from host to display. There are two numbers that contol timings: wr_up_delay and wr_down_delay. They should be provided by the display driver. The first number is related to the write control pulse duration, and the second number is related to the write cycle duration that can be found in the specification of the display.
Signed-off-by: Mikhail Durnev mikhail_durnev@mentor.com --- drivers/gpu/drm/drm_mipi_dbi.c | 134 ++++++++++++++++++++++++++++++++++++++--- include/drm/drm_mipi_dbi.h | 30 ++++++++- 2 files changed, 153 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index 230c4fd..3edb041 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -61,7 +61,7 @@ * 3. 8-bit with the Data/Command signal as a separate D/CX pin * * Currently mipi_dbi only supports Type C options 1 and 3 with - * mipi_dbi_spi_init(). + * mipi_dbi_spi_init() and Type B with mipi_dbi_gpio_init(). */
#define MIPI_DBI_DEBUG_COMMAND(cmd, data, len) \ @@ -701,6 +701,15 @@ int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev) } EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
+static bool mipi_dbi_machine_little_endian(void) +{ +#if defined(__LITTLE_ENDIAN) + return true; +#else + return false; +#endif +} + #if IS_ENABLED(CONFIG_SPI)
/** @@ -721,15 +730,6 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len) } EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed);
-static bool mipi_dbi_machine_little_endian(void) -{ -#if defined(__LITTLE_ENDIAN) - return true; -#else - return false; -#endif -} - /* * MIPI DBI Type C Option 1 * @@ -1158,6 +1158,120 @@ EXPORT_SYMBOL(mipi_dbi_spi_transfer);
#endif /* CONFIG_SPI */
+/* + * This function implements data transfer only from host to display. + */ +static void mipi_dbi_gpio_transfer(struct mipi_dbi *dbi, u16 data) +{ + unsigned long ldata = data; + + /* + * Set W/R to low to start transfer. + * Set DB bits with provided data when W/R is low. + */ + gpiod_set_value_cansleep(dbi->wr, 0); + gpiod_set_array_value_cansleep(dbi->db->ndescs, dbi->db->desc, + dbi->db->info, &ldata); + + /* + * The bus usually needs additional delay. + */ + ndelay(dbi->wr_up_delay); + + /* + * Set W/R to high to indicate that DB lines are set. + */ + gpiod_set_value_cansleep(dbi->wr, 1); + + /* + * The connected display needs some time to read the data. + */ + ndelay(dbi->wr_down_delay); +} + +static int mipi_dbi_gpio_command(struct mipi_dbi *dbi, u8 *cmd, + u8 *par, size_t num) +{ + int i; + + /* + * Read commands are not currently supported. + */ + if (mipi_dbi_command_is_read(dbi, *cmd)) + return -EOPNOTSUPP; + + MIPI_DBI_DEBUG_COMMAND(*cmd, par, num); + + gpiod_set_value_cansleep(dbi->dc, 0); + mipi_dbi_gpio_transfer(dbi, (u16)*cmd); + gpiod_set_value_cansleep(dbi->dc, 1); + + if (dbi->db->ndescs == 16 && + (*cmd == MIPI_DCS_WRITE_MEMORY_START || + *cmd == MIPI_DCS_WRITE_MEMORY_CONTINUE)) { + /* + * Only a couple of commands supports 16-bit transfer. + */ + for (i = 0; i < num; i += 2) { + u16 data = *(u16 *)&par[i]; + + if (dbi->swap_bytes) + data = (data >> 8) | (data << 8); + + mipi_dbi_gpio_transfer(dbi, data); + } + } else { + for (i = 0; i < num; i++) { + /* + * Other commands ignore most significant bits. + */ + mipi_dbi_gpio_transfer(dbi, (u16)par[i]); + } + } + + return 0; +} + +/** + * mipi_dbi_gpio_init - Initialize MIPI DBI Type B interface implemented via GPIO + * @dbi: MIPI DBI structure to initialize + * @dc: D/C gpio + * @wr: W/R gpio + * @db: DB gpios + * @wr_up_delay: Delay after setting DB and before changing W/R from low to high + * @wr_down_delay: Delay after changing W/R from low to high + * + * This function sets &mipi_dbi->command, enables &mipi_dbi->read_commands for the + * usual read commands. It should be followed by a call to mipi_dbi_dev_init() or + * a driver-specific init. + * + * Returns: + * Zero on success, negative error code on failure. + */ +int mipi_dbi_gpio_init(struct mipi_dbi *dbi, struct gpio_desc *dc, + struct gpio_desc *wr, struct gpio_descs *db, + unsigned long wr_up_delay, unsigned long wr_down_delay) +{ + dbi->spi = NULL; /* Type B uses GPIO lines rather than SPI */ + + dbi->read_commands = mipi_dbi_dcs_read_commands; + dbi->command = mipi_dbi_gpio_command; + + dbi->dc = dc; + dbi->wr = wr; + dbi->db = db; + dbi->wr_up_delay = wr_up_delay; + dbi->wr_down_delay = wr_down_delay; + + if (mipi_dbi_machine_little_endian()) + dbi->swap_bytes = true; + + mutex_init(&dbi->cmdlock); + + return 0; +} +EXPORT_SYMBOL(mipi_dbi_gpio_init); + #ifdef CONFIG_DEBUG_FS
static ssize_t mipi_dbi_debugfs_command_write(struct file *file, diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index c2827ce..c4be5ca 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -55,7 +55,7 @@ struct mipi_dbi { struct spi_device *spi;
/** - * @dc: Optional D/C gpio. + * @dc: D/C gpio, optional for Type C and mandatory for Type B. */ struct gpio_desc *dc;
@@ -68,6 +68,31 @@ struct mipi_dbi { * @tx_buf9_len: Size of tx_buf9. */ size_t tx_buf9_len; + + /* Type B specific */ + + /** + * @wr: W/R gpio. + */ + struct gpio_desc *wr; + + /** + * @db: Data Bus gpios (usually 8 or 16). + */ + struct gpio_descs *db; + + /** + * @wr_up_delay: Delay after setting all db lines and before changing + * wr from low to high. + */ + unsigned long wr_up_delay; + + /** + * @wr_down_delay: Delay after changing wr from low to high and + * before wr can be changed again from hight to low to start a new + * write operation. + */ + unsigned long wr_down_delay; };
/** @@ -139,6 +164,9 @@ static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm)
int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, struct gpio_desc *dc); +int mipi_dbi_gpio_init(struct mipi_dbi *dbi, struct gpio_desc *dc, + struct gpio_desc *wr, struct gpio_descs *db, + unsigned long wr_up_delay, unsigned long wr_down_delay); int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, const struct drm_simple_display_pipe_funcs *funcs, const uint32_t *formats, unsigned int format_count,
From: Mikhail Durnev mikhail_durnev@mentor.com
MRB2801 display module [1] is an example of ILI9341 display that connects to Intel 8080 parallel bus. Its connector is compatible with the ALIENTEK STM32 development board.
It can be used with the drm/mipi-dbi bus driver if the bus is emulated with GPIO.
[1] http://www.lcdwiki.com/2.8inch_16BIT_Module_ILI9341_SKU:MRB2801
Signed-off-by: Mikhail Durnev mikhail_durnev@mentor.com --- drivers/gpu/drm/tiny/Kconfig | 13 ++ drivers/gpu/drm/tiny/Makefile | 1 + drivers/gpu/drm/tiny/ili9341_gpio.c | 290 ++++++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+) create mode 100644 drivers/gpu/drm/tiny/ili9341_gpio.c
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 2b6414f..e48e268 100644 --- a/drivers/gpu/drm/tiny/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -66,6 +66,19 @@ config TINYDRM_ILI9341
If M is selected the module will be called ili9341.
+config TINYDRM_ILI9341_GPIO + tristate "DRM support for ILI9341 display panels with parallel bus interface over GPIO" + depends on DRM + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI + select BACKLIGHT_CLASS_DEVICE + help + DRM driver for the following Ilitek ILI9341 panels: + * MRB2801 2.8" 240x320 TFT + + If M is selected the module will be called ili9341_gpio. + config TINYDRM_ILI9486 tristate "DRM support for ILI9486 display panels" depends on DRM && SPI diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile index 6ae4e9e5..1ad2c0d 100644 --- a/drivers/gpu/drm/tiny/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_DRM_GM12U320) += gm12u320.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o obj-$(CONFIG_TINYDRM_ILI9341) += ili9341.o +obj-$(CONFIG_TINYDRM_ILI9341_GPIO) += ili9341_gpio.o obj-$(CONFIG_TINYDRM_ILI9486) += ili9486.o obj-$(CONFIG_TINYDRM_MI0283QT) += mi0283qt.o obj-$(CONFIG_TINYDRM_REPAPER) += repaper.o diff --git a/drivers/gpu/drm/tiny/ili9341_gpio.c b/drivers/gpu/drm/tiny/ili9341_gpio.c new file mode 100644 index 0000000..de8a63b8 --- /dev/null +++ b/drivers/gpu/drm/tiny/ili9341_gpio.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * DRM driver for Ilitek ILI9341 panels with parallel bus interface + * + * Copyright 2020 Mikhail Durnev mikhail_durnev@mentor.com + * + * Based on ili9341.c: + * Copyright 2018 David Lechner david@lechnology.com + * + * Based on mi0283qt.c: + * Copyright 2016 Noralf Trønnes + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/property.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_mipi_dbi.h> +#include <drm/drm_modeset_helper.h> +#include <video/mipi_display.h> + +#define ILI9341_FRMCTR1 0xb1 +#define ILI9341_DISCTRL 0xb6 +#define ILI9341_ETMOD 0xb7 + +#define ILI9341_PWCTRL1 0xc0 +#define ILI9341_PWCTRL2 0xc1 +#define ILI9341_VMCTRL1 0xc5 +#define ILI9341_VMCTRL2 0xc7 +#define ILI9341_PWCTRLA 0xcb +#define ILI9341_PWCTRLB 0xcf + +#define ILI9341_PGAMCTRL 0xe0 +#define ILI9341_NGAMCTRL 0xe1 +#define ILI9341_DTCTRLA 0xe8 +#define ILI9341_DTCTRLB 0xea +#define ILI9341_PWRSEQ 0xed + +#define ILI9341_EN3GAM 0xf2 +#define ILI9341_PUMPCTRL 0xf7 + +#define ILI9341_MADCTL_BGR BIT(3) +#define ILI9341_MADCTL_MV BIT(5) +#define ILI9341_MADCTL_MX BIT(6) +#define ILI9341_MADCTL_MY BIT(7) + +static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) +{ + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; + u8 addr_mode; + int ret, idx; + + if (!drm_dev_enter(pipe->crtc.dev, &idx)) + return; + + DRM_DEBUG_KMS("\n"); + + ret = mipi_dbi_poweron_conditional_reset(dbidev); + if (ret < 0) + goto out_exit; + if (ret == 1) + goto out_enable; + + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); + + mipi_dbi_command(dbi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30); + mipi_dbi_command(dbi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81); + mipi_dbi_command(dbi, ILI9341_DTCTRLA, 0x85, 0x00, 0x78); + mipi_dbi_command(dbi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02); + mipi_dbi_command(dbi, ILI9341_PUMPCTRL, 0x20); + mipi_dbi_command(dbi, ILI9341_DTCTRLB, 0x00, 0x00); + + /* Power Control */ + mipi_dbi_command(dbi, ILI9341_PWCTRL1, 0x23); + mipi_dbi_command(dbi, ILI9341_PWCTRL2, 0x10); + /* VCOM */ + mipi_dbi_command(dbi, ILI9341_VMCTRL1, 0x3e, 0x28); + mipi_dbi_command(dbi, ILI9341_VMCTRL2, 0x86); + + /* Memory Access Control */ + mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); + + /* Frame Rate */ + mipi_dbi_command(dbi, ILI9341_FRMCTR1, 0x00, 0x1b); + + /* Gamma */ + mipi_dbi_command(dbi, ILI9341_EN3GAM, 0x00); + mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x01); + mipi_dbi_command(dbi, ILI9341_PGAMCTRL, + 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1, + 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00); + mipi_dbi_command(dbi, ILI9341_NGAMCTRL, + 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1, + 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f); + + /* DDRAM */ + mipi_dbi_command(dbi, ILI9341_ETMOD, 0x07); + + /* Display */ + mipi_dbi_command(dbi, ILI9341_DISCTRL, 0x08, 0x82, 0x27, 0x00); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); + msleep(100); + + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); + msleep(100); + +out_enable: + switch (dbidev->rotation) { + default: + addr_mode = ILI9341_MADCTL_MX; + break; + case 90: + addr_mode = ILI9341_MADCTL_MV; + break; + case 180: + addr_mode = ILI9341_MADCTL_MY; + break; + case 270: + addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY | + ILI9341_MADCTL_MX; + break; + } + addr_mode |= ILI9341_MADCTL_BGR; + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); +out_exit: + drm_dev_exit(idx); +} + +static const struct drm_simple_display_pipe_funcs ili9341gpio_pipe_funcs = { + .enable = yx240qv29_enable, + .disable = mipi_dbi_pipe_disable, + .update = mipi_dbi_pipe_update, + .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, +}; + +static const struct drm_display_mode yx240qv29_mode = { + DRM_SIMPLE_MODE(240, 320, 37, 49), +}; + +DEFINE_DRM_GEM_CMA_FOPS(ili9341gpio_fops); + +static struct drm_driver ili9341gpio_driver = { + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, + .fops = &ili9341gpio_fops, + .release = mipi_dbi_release, + DRM_GEM_CMA_VMAP_DRIVER_OPS, + .debugfs_init = mipi_dbi_debugfs_init, + .name = "ili9341gpio", + .desc = "Ilitek ILI9341", + .date = "20201114", + .major = 1, + .minor = 0, +}; + +static const struct of_device_id ili9341gpio_of_match[] = { + { .compatible = "ronbo,mrb2801" }, + { } +}; +MODULE_DEVICE_TABLE(of, ili9341gpio_of_match); + +static int ili9341gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mipi_dbi_dev *dbidev; + struct drm_device *drm; + struct mipi_dbi *dbi; + struct gpio_desc *dc; + struct gpio_desc *wr; + struct gpio_descs *db; + u32 rotation = 0; + u32 wr_delays[2] = {15, 60}; + int ret; + + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) + return -ENOMEM; + + dbi = &dbidev->dbi; + drm = &dbidev->drm; + ret = devm_drm_dev_init(dev, drm, &ili9341gpio_driver); + if (ret) { + kfree(dbidev); + return ret; + } + + drm_mode_config_init(drm); + + dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); + return PTR_ERR(dbi->reset); + } + + dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_HIGH); + if (IS_ERR(dc)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); + return PTR_ERR(dc); + } + + wr = devm_gpiod_get(dev, "wr", GPIOD_OUT_HIGH); + if (IS_ERR(wr)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'wr'\n"); + return PTR_ERR(wr); + } + + db = devm_gpiod_get_array(dev, "db", GPIOD_OUT_LOW); + if (IS_ERR(db)) { + DRM_DEV_ERROR(dev, "Failed to get gpio 'db'\n"); + return PTR_ERR(db); + } + if (db->ndescs != 16 && db->ndescs != 8) { + /* + * The data bus can be either 8 or 16 bits wide. + * ILI9341 can work with 6, 8, 9, 16, and 18-bit parallel interfaces, + * but the MRB2801 board supports only 8 or 16-bit interfaces. + */ + DRM_DEV_ERROR(dev, "Wrong number of bits in gpio 'db': %u\n", db->ndescs); + return PTR_ERR(db); + } + + dbidev->backlight = devm_of_find_backlight(dev); + if (IS_ERR(dbidev->backlight)) + return PTR_ERR(dbidev->backlight); + + device_property_read_u32(dev, "rotation", &rotation); + + device_property_read_u32_array(dev, "wr-up-down-delays", wr_delays, 2); + + ret = mipi_dbi_gpio_init(dbi, dc, wr, db, wr_delays[0], wr_delays[1]); + if (ret) + return ret; + + ret = mipi_dbi_dev_init(dbidev, &ili9341gpio_pipe_funcs, &yx240qv29_mode, rotation); + if (ret) + return ret; + + drm_mode_config_reset(drm); + + ret = drm_dev_register(drm, 0); + if (ret) + return ret; + + platform_set_drvdata(pdev, drm); + + drm_fbdev_generic_setup(drm, 0); + + return 0; +} + +static int ili9341gpio_remove(struct platform_device *pdev) +{ + struct drm_device *drm = platform_get_drvdata(pdev); + + drm_dev_unplug(drm); + drm_atomic_helper_shutdown(drm); + + return 0; +} + +static void ili9341gpio_shutdown(struct platform_device *pdev) +{ + drm_atomic_helper_shutdown(platform_get_drvdata(pdev)); +} + +static struct platform_driver ili9341gpio_platform_driver = { + .driver = { + .name = "ili9341gpio", + .of_match_table = ili9341gpio_of_match, + }, + .probe = ili9341gpio_probe, + .remove = ili9341gpio_remove, + .shutdown = ili9341gpio_shutdown, +}; +module_platform_driver(ili9341gpio_platform_driver); + +MODULE_DESCRIPTION("Ilitek ILI9341 8/16-bit DRM driver"); +MODULE_AUTHOR("Mikhail Durnev mikhail_durnev@mentor.com"); +MODULE_LICENSE("GPL");
Hi,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linux/master] [also build test ERROR on drm-intel/for-linux-next drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next drm-tip/drm-tip linus/master v5.10-rc6 next-20201201] [cannot apply to drm/drm-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/mdurnev-gmail-com/drm-mipi-dbi-Type... base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 09162bc32c880a791c6c0668ce0745cf7958f576 config: riscv-randconfig-r024-20201202 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 2671fccf0381769276ca8246ec0499adcb9b0355) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install riscv cross compiling tool for clang build # apt-get install binutils-riscv64-linux-gnu # https://github.com/0day-ci/linux/commit/6d76a991fa9d2c883126667b704c729eaa22... git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review mdurnev-gmail-com/drm-mipi-dbi-Type-B-bus-support-drm-tiny-MRB2801/20201201-071109 git checkout 6d76a991fa9d2c883126667b704c729eaa22df0e # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv
If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot lkp@intel.com
All errors (new ones prefixed by >>):
drivers/gpu/drm/tiny/ili9341_gpio.c:157:14: error: use of undeclared identifier 'mipi_dbi_release'; did you mean 'mipi_dbi_hw_reset'?
.release = mipi_dbi_release, ^~~~~~~~~~~~~~~~ mipi_dbi_hw_reset include/drm/drm_mipi_dbi.h:184:6: note: 'mipi_dbi_hw_reset' declared here void mipi_dbi_hw_reset(struct mipi_dbi *dbi); ^
drivers/gpu/drm/tiny/ili9341_gpio.c:158:2: error: use of undeclared identifier 'DRM_GEM_CMA_VMAP_DRIVER_OPS'
DRM_GEM_CMA_VMAP_DRIVER_OPS, ^
drivers/gpu/drm/tiny/ili9341_gpio.c:192:8: error: implicit declaration of function 'devm_drm_dev_init' [-Werror,-Wimplicit-function-declaration]
ret = devm_drm_dev_init(dev, drm, &ili9341gpio_driver); ^ 3 errors generated.
vim +157 drivers/gpu/drm/tiny/ili9341_gpio.c
153 154 static struct drm_driver ili9341gpio_driver = { 155 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 156 .fops = &ili9341gpio_fops,
157 .release = mipi_dbi_release, 158 DRM_GEM_CMA_VMAP_DRIVER_OPS,
159 .debugfs_init = mipi_dbi_debugfs_init, 160 .name = "ili9341gpio", 161 .desc = "Ilitek ILI9341", 162 .date = "20201114", 163 .major = 1, 164 .minor = 0, 165 }; 166 167 static const struct of_device_id ili9341gpio_of_match[] = { 168 { .compatible = "ronbo,mrb2801" }, 169 { } 170 }; 171 MODULE_DEVICE_TABLE(of, ili9341gpio_of_match); 172 173 static int ili9341gpio_probe(struct platform_device *pdev) 174 { 175 struct device *dev = &pdev->dev; 176 struct mipi_dbi_dev *dbidev; 177 struct drm_device *drm; 178 struct mipi_dbi *dbi; 179 struct gpio_desc *dc; 180 struct gpio_desc *wr; 181 struct gpio_descs *db; 182 u32 rotation = 0; 183 u32 wr_delays[2] = {15, 60}; 184 int ret; 185 186 dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); 187 if (!dbidev) 188 return -ENOMEM; 189 190 dbi = &dbidev->dbi; 191 drm = &dbidev->drm;
192 ret = devm_drm_dev_init(dev, drm, &ili9341gpio_driver);
193 if (ret) { 194 kfree(dbidev); 195 return ret; 196 } 197 198 drm_mode_config_init(drm); 199 200 dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); 201 if (IS_ERR(dbi->reset)) { 202 DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); 203 return PTR_ERR(dbi->reset); 204 } 205 206 dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_HIGH); 207 if (IS_ERR(dc)) { 208 DRM_DEV_ERROR(dev, "Failed to get gpio 'dc'\n"); 209 return PTR_ERR(dc); 210 } 211 212 wr = devm_gpiod_get(dev, "wr", GPIOD_OUT_HIGH); 213 if (IS_ERR(wr)) { 214 DRM_DEV_ERROR(dev, "Failed to get gpio 'wr'\n"); 215 return PTR_ERR(wr); 216 } 217 218 db = devm_gpiod_get_array(dev, "db", GPIOD_OUT_LOW); 219 if (IS_ERR(db)) { 220 DRM_DEV_ERROR(dev, "Failed to get gpio 'db'\n"); 221 return PTR_ERR(db); 222 } 223 if (db->ndescs != 16 && db->ndescs != 8) { 224 /* 225 * The data bus can be either 8 or 16 bits wide. 226 * ILI9341 can work with 6, 8, 9, 16, and 18-bit parallel interfaces, 227 * but the MRB2801 board supports only 8 or 16-bit interfaces. 228 */ 229 DRM_DEV_ERROR(dev, "Wrong number of bits in gpio 'db': %u\n", db->ndescs); 230 return PTR_ERR(db); 231 } 232 233 dbidev->backlight = devm_of_find_backlight(dev); 234 if (IS_ERR(dbidev->backlight)) 235 return PTR_ERR(dbidev->backlight); 236 237 device_property_read_u32(dev, "rotation", &rotation); 238 239 device_property_read_u32_array(dev, "wr-up-down-delays", wr_delays, 2); 240 241 ret = mipi_dbi_gpio_init(dbi, dc, wr, db, wr_delays[0], wr_delays[1]); 242 if (ret) 243 return ret; 244 245 ret = mipi_dbi_dev_init(dbidev, &ili9341gpio_pipe_funcs, &yx240qv29_mode, rotation); 246 if (ret) 247 return ret; 248 249 drm_mode_config_reset(drm); 250 251 ret = drm_dev_register(drm, 0); 252 if (ret) 253 return ret; 254 255 platform_set_drvdata(pdev, drm); 256 257 drm_fbdev_generic_setup(drm, 0); 258 259 return 0; 260 } 261
--- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
From: Mikhail Durnev mikhail_durnev@mentor.com
Add binding for Ronbo MRB2801 display module.
This binding is for display panels using an Ilitek ILI9341 controller in parallel mode.
Signed-off-by: Mikhail Durnev mikhail_durnev@mentor.com --- .../devicetree/bindings/display/ronbo,mrb2801.txt | 42 ++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/ronbo,mrb2801.txt
diff --git a/Documentation/devicetree/bindings/display/ronbo,mrb2801.txt b/Documentation/devicetree/bindings/display/ronbo,mrb2801.txt new file mode 100644 index 0000000..db1a861e --- /dev/null +++ b/Documentation/devicetree/bindings/display/ronbo,mrb2801.txt @@ -0,0 +1,42 @@ +MRB2801 display panel + +This binding is for display panels using an Ilitek ILI9341 controller in +parallel mode. + +Required properties: +- compatible: "ronbo,mrb2801" +- dc-gpios: D/C pin +- wr-gpios: W/R pin +- db-gpios: 8 or 16 DB pins +- reset-gpios: Reset pin +- wr-up-down-delays: Delays in ns for changing W/R from down to up and from up to down + +Optional properties: +- backlight: phandle of the backlight device attached to the panel +- rotation: panel rotation in degrees counter clockwise (0,90,180,270) + +Example: + mrb2801{ + compatible = "ronbo,mrb2801"; + db-gpios = <&gpio 17 0>, /* DB0 */ + <&gpio 18 0>, /* DB1 */ + <&gpio 27 0>, /* DB2 */ + <&gpio 22 0>, /* DB3 */ + <&gpio 23 0>, /* DB4 */ + <&gpio 24 0>, /* DB5 */ + <&gpio 25 0>, /* DB6 */ + <&gpio 4 0>, /* DB7 */ + <&gpio 14 0>, /* DB8 */ + <&gpio 15 0>, /* DB9 */ + <&gpio 5 0>, /* DB10 */ + <&gpio 6 0>, /* DB11 */ + <&gpio 13 0>, /* DB12 */ + <&gpio 19 0>, /* DB13 */ + <&gpio 26 0>, /* DB14 */ + <&gpio 12 0>; /* DB15 */ + dc-gpios = <&gpio 16 0>; /* D/C */ + wr-gpios = <&gpio 20 0>; /* W/R */ + wr-up-down-delays = <10 51>; + reset-gpios = <&gpio 21 0>; /* RST */ + backlight = <&backlight>; + };
dri-devel@lists.freedesktop.org