[PATCH v2 0/3] drm/mipi-dbi: Type B bus support, drm/tiny: MRB2801

2020-11-30 Thread mdurnev
From: Mikhail Durnev 

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 

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

-- 
2.7.4



[PATCH v2 1/3] drm/mipi-dbi: Add support for Type B

2020-11-30 Thread mdurnev
From: Mikhail Durnev 

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 
---
 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, enable

[PATCH v2 3/3] dt-bindings: panel: Add bindings for MRB2801

2020-11-30 Thread mdurnev
From: Mikhail Durnev 

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 
---
 .../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 000..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>;
+   };
-- 
2.7.4



[PATCH v2 2/3] drm/tiny: Add driver for ili9341 with parallel bus

2020-11-30 Thread mdurnev
From: Mikhail Durnev 

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 
---
 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 000..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 
+ *
+ * Based on ili9341.c:
+ * Copyright 2018 David Lechner 
+ *
+ * Based on mi0283qt.c:
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ILI9341_FRMCTR10xb1
+#define ILI9341_DISCTRL0xb6
+#define ILI9341_ETMOD  0xb7
+
+#define ILI9341_PWCTRL10xc0
+#define ILI9341_PWCTRL20xc1
+#define ILI9341_VMCTRL10xc5
+#define ILI9341_VMCTRL20xc7
+#define ILI9341_PWCTRLA0xcb
+#define ILI9341_PWCTRLB0xcf
+
+#define ILI9341_PGAMCTRL   0xe0
+#define ILI9341_NGAMCTRL   0xe1
+#define ILI9341_DTCTRLA0xe8
+#define ILI9341_DTCTRLB0xea
+#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

[PATCH v0] ASoC: rsnd: core: Check convert rate in rsnd_hw_params

2020-12-02 Thread mdurnev
From: Mikhail Durnev 

snd_pcm_hw_params_set_rate_near can return incorrect sample rate in
some cases, e.g. when the backend output rate is set to some value higher
than 48000 Hz and the input rate is 8000 Hz. So passing the value returned
by snd_pcm_hw_params_set_rate_near to snd_pcm_hw_params will result in
"FSO/FSI ratio error" and playing no audio at all while the userland
is not properly notified about the issue.

If SRC is unable to convert the requested sample rate to the sample rate
the backend is using, then the requested sample rate should be adjusted in
rsnd_hw_params. The userland will be notified about that change in the
returned hw_params structure.

Signed-off-by: Mikhail Durnev 
---
 sound/soc/sh/rcar/core.c | 67 +++-
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 6e670b3..8ca3fb7 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1428,8 +1428,73 @@ static int rsnd_hw_params(struct snd_soc_component 
*component,
}
if (io->converted_chan)
dev_dbg(dev, "convert channels = %d\n", 
io->converted_chan);
-   if (io->converted_rate)
+   if (io->converted_rate) {
dev_dbg(dev, "convert rate = %d\n", 
io->converted_rate);
+
+   /*
+* SRC supports convert rates from 
params_rate(hw_params)/k_down
+* to params_rate(hw_params)*k_up, where k_up is always 
6, and
+* k_down depends on number of channels and SRC unit.
+* So all SRC units can upsample audio up to 6 times 
regardless
+* its number of channels. And all SRC units can 
downsample
+* 2 channel audio up to 6 times too.
+*/
+   int k_up = 6;
+   int k_down = 6;
+   int channel;
+   struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
+
+   channel = io->converted_chan ? io->converted_chan : 
fe_channel;
+
+   switch (rsnd_mod_id(src_mod)) {
+   /*
+* SRC0 can downsample 4, 6 and 8 channel audio up to 4 
times.
+* SRC1, SRC3 and SRC4 can downsample 4 channel audio
+* up to 4 times.
+* SRC1, SRC3 and SRC4 can downsample 6 and 8 channel 
audio
+* no more than twice.
+*/
+   case 1:
+   case 3:
+   case 4:
+   if (channel > 4) {
+   k_down = 2;
+   break;
+   }
+   case 0:
+   if (channel > 2)
+   k_down = 4;
+   break;
+
+   /* Other SRC units do not support more than 2 channels 
*/
+   default:
+   if (channel > 2)
+   return -EINVAL;
+   }
+
+   if (params_rate(hw_params) > io->converted_rate * 
k_down) {
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->min =
+   io->converted_rate * k_down;
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->max =
+   io->converted_rate * k_down;
+   hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+   } else if (params_rate(hw_params) * k_up < 
io->converted_rate) {
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->min =
+   (io->converted_rate + k_up - 1) / k_up;
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->max =
+   (io->converted_rate + k_up - 1) / k_up;
+   hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+   }
+
+   /*
+* TBD: Max SRC input and output rates also depend on 
number
+* of channels and SRC unit:
+* SRC1, SRC3 and SRC4 do not support more than 128kHz
+* for 6 channel and 96kHz for 8 channel audio.
+* Perhaps this function should return EINVAL if the 
input or
+* the output rate exceeds the limitation.
+*/
+   }
}
 
return rsnd_dai_call(hw_params, io, substream, hw_p

[PATCH v1] ASoC: rsnd: core: Check convert rate in rsnd_hw_params

2020-12-02 Thread mdurnev
From: Mikhail Durnev 

snd_pcm_hw_params_set_rate_near can return incorrect sample rate in
some cases, e.g. when the backend output rate is set to some value higher
than 48000 Hz and the input rate is 8000 Hz. So passing the value returned
by snd_pcm_hw_params_set_rate_near to snd_pcm_hw_params will result in
"FSO/FSI ratio error" and playing no audio at all while the userland
is not properly notified about the issue.

If SRC is unable to convert the requested sample rate to the sample rate
the backend is using, then the requested sample rate should be adjusted in
rsnd_hw_params. The userland will be notified about that change in the
returned hw_params structure.

Signed-off-by: Mikhail Durnev 
---
 sound/soc/sh/rcar/core.c | 69 +++-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index 6e670b3..289928d 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1428,8 +1428,75 @@ static int rsnd_hw_params(struct snd_soc_component 
*component,
}
if (io->converted_chan)
dev_dbg(dev, "convert channels = %d\n", 
io->converted_chan);
-   if (io->converted_rate)
+   if (io->converted_rate) {
+   /*
+* SRC supports convert rates from 
params_rate(hw_params)/k_down
+* to params_rate(hw_params)*k_up, where k_up is always 
6, and
+* k_down depends on number of channels and SRC unit.
+* So all SRC units can upsample audio up to 6 times 
regardless
+* its number of channels. And all SRC units can 
downsample
+* 2 channel audio up to 6 times too.
+*/
+   int k_up = 6;
+   int k_down = 6;
+   int channel;
+   struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
+
dev_dbg(dev, "convert rate = %d\n", 
io->converted_rate);
+
+   channel = io->converted_chan ? io->converted_chan :
+ params_channels(hw_params);
+
+   switch (rsnd_mod_id(src_mod)) {
+   /*
+* SRC0 can downsample 4, 6 and 8 channel audio up to 4 
times.
+* SRC1, SRC3 and SRC4 can downsample 4 channel audio
+* up to 4 times.
+* SRC1, SRC3 and SRC4 can downsample 6 and 8 channel 
audio
+* no more than twice.
+*/
+   case 1:
+   case 3:
+   case 4:
+   if (channel > 4) {
+   k_down = 2;
+   break;
+   }
+   fallthrough;
+   case 0:
+   if (channel > 2)
+   k_down = 4;
+   break;
+
+   /* Other SRC units do not support more than 2 channels 
*/
+   default:
+   if (channel > 2)
+   return -EINVAL;
+   }
+
+   if (params_rate(hw_params) > io->converted_rate * 
k_down) {
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->min =
+   io->converted_rate * k_down;
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->max =
+   io->converted_rate * k_down;
+   hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+   } else if (params_rate(hw_params) * k_up < 
io->converted_rate) {
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->min =
+   (io->converted_rate + k_up - 1) / k_up;
+   hw_param_interval(hw_params, 
SNDRV_PCM_HW_PARAM_RATE)->max =
+   (io->converted_rate + k_up - 1) / k_up;
+   hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE;
+   }
+
+   /*
+* TBD: Max SRC input and output rates also depend on 
number
+* of channels and SRC unit:
+* SRC1, SRC3 and SRC4 do not support more than 128kHz
+* for 6 channel and 96kHz for 8 channel audio.
+* Perhaps this function should return EINVAL if the 
input or
+* the output rate exceeds the limitation.
+  

[PATCH v3 1/3] drm/mipi-dbi: Add support for Type B

2020-12-03 Thread mdurnev
From: Mikhail Durnev 

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 
---
 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, enable

[PATCH v3 2/3] drm/tiny: Add driver for ili9341 with parallel bus

2020-12-03 Thread mdurnev
From: Mikhail Durnev 

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 
---
 drivers/gpu/drm/tiny/Kconfig|  13 ++
 drivers/gpu/drm/tiny/Makefile   |   1 +
 drivers/gpu/drm/tiny/ili9341_gpio.c | 284 
 3 files changed, 298 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 000..841f01c
--- /dev/null
+++ b/drivers/gpu/drm/tiny/ili9341_gpio.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * DRM driver for Ilitek ILI9341 panels with parallel bus interface
+ *
+ * Copyright 2020 Mikhail Durnev 
+ *
+ * Based on ili9341.c:
+ * Copyright 2018 David Lechner 
+ *
+ * Based on mi0283qt.c:
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ILI9341_FRMCTR10xb1
+#define ILI9341_DISCTRL0xb6
+#define ILI9341_ETMOD  0xb7
+
+#define ILI9341_PWCTRL10xc0
+#define ILI9341_PWCTRL20xc1
+#define ILI9341_VMCTRL10xc5
+#define ILI9341_VMCTRL20xc7
+#define ILI9341_PWCTRLA0xcb
+#define ILI9341_PWCTRLB0xcf
+
+#define ILI9341_PGAMCTRL   0xe0
+#define ILI9341_NGAMCTRL   0xe1
+#define ILI9341_DTCTRLA0xe8
+#define ILI9341_DTCTRLB0xea
+#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);
+
+  

[PATCH v3 3/3] dt-bindings: panel: Add bindings for MRB2801

2020-12-03 Thread mdurnev
From: Mikhail Durnev 

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 
---
 .../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 000..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>;
+   };
-- 
2.7.4



[PATCH v3 0/3] drm/mipi-dbi: Type B bus support, drm/tiny: MRB2801

2020-12-03 Thread mdurnev
From: Mikhail Durnev 

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 

v2 -> v3:
- Fixed build errors reported by the kernel test robot

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| 284 +
 include/drm/drm_mipi_dbi.h |  30 ++-
 6 files changed, 493 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/ronbo,mrb2801.txt
 create mode 100644 drivers/gpu/drm/tiny/ili9341_gpio.c

-- 
2.7.4



[PATCH v1 1/3] drm/mipi-dbi: Add support for Type B

2020-11-29 Thread mdurnev
From: Mikhail Durnev 

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 
---
 drivers/gpu/drm/drm_mipi_dbi.c | 116 -
 include/drm/drm_mipi_dbi.h |  30 ++-
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 230c4fd..5dedc59 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) \
@@ -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;
+   db

[PATCH v1 2/3] drm/tiny: Add driver for ili9341 with parallel bus

2020-11-29 Thread mdurnev
From: Mikhail Durnev 

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 
---
 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 000..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 
+ *
+ * Based on ili9341.c:
+ * Copyright 2018 David Lechner 
+ *
+ * Based on mi0283qt.c:
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ILI9341_FRMCTR10xb1
+#define ILI9341_DISCTRL0xb6
+#define ILI9341_ETMOD  0xb7
+
+#define ILI9341_PWCTRL10xc0
+#define ILI9341_PWCTRL20xc1
+#define ILI9341_VMCTRL10xc5
+#define ILI9341_VMCTRL20xc7
+#define ILI9341_PWCTRLA0xcb
+#define ILI9341_PWCTRLB0xcf
+
+#define ILI9341_PGAMCTRL   0xe0
+#define ILI9341_NGAMCTRL   0xe1
+#define ILI9341_DTCTRLA0xe8
+#define ILI9341_DTCTRLB0xea
+#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

[PATCH v1 0/3] drm/mipi-dbi: Type B bus support, drm/tiny: MRB2801

2020-11-29 Thread mdurnev
From: Mikhail Durnev 

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

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 | 116 -
 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, 490 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/ronbo,mrb2801.txt
 create mode 100644 drivers/gpu/drm/tiny/ili9341_gpio.c

-- 
2.7.4



[PATCH v1 3/3] dt-bindings: panel: Add bindings for MRB2801

2020-11-29 Thread mdurnev
From: Mikhail Durnev 

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 
---
 .../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 000..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>;
+   };
-- 
2.7.4



[PATCH 1/3] drm/mipi-dbi: Add support for Type B

2020-11-17 Thread mdurnev
From: Mikhail Durnev 

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 
---
 drivers/gpu/drm/drm_mipi_dbi.c | 116 -
 include/drm/drm_mipi_dbi.h |  30 ++-
 2 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c
index 230c4fd..4d2e108 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) \
@@ -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 = 0; /* 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->

[PATCH 0/3] drm/mipi-dbi: Type B bus support, drm/tiny: MRB2801

2020-11-17 Thread mdurnev
From: Mikhail Durnev 

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

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 | 116 -
 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, 490 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/display/ronbo,mrb2801.txt
 create mode 100644 drivers/gpu/drm/tiny/ili9341_gpio.c

-- 
2.7.4



[PATCH 2/3] drm/tiny: Add driver for ili9341 with parallel bus

2020-11-17 Thread mdurnev
From: Mikhail Durnev 

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 
---
 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 000..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 
+ *
+ * Based on ili9341.c:
+ * Copyright 2018 David Lechner 
+ *
+ * Based on mi0283qt.c:
+ * Copyright 2016 Noralf Trønnes
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ILI9341_FRMCTR10xb1
+#define ILI9341_DISCTRL0xb6
+#define ILI9341_ETMOD  0xb7
+
+#define ILI9341_PWCTRL10xc0
+#define ILI9341_PWCTRL20xc1
+#define ILI9341_VMCTRL10xc5
+#define ILI9341_VMCTRL20xc7
+#define ILI9341_PWCTRLA0xcb
+#define ILI9341_PWCTRLB0xcf
+
+#define ILI9341_PGAMCTRL   0xe0
+#define ILI9341_NGAMCTRL   0xe1
+#define ILI9341_DTCTRLA0xe8
+#define ILI9341_DTCTRLB0xea
+#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

[PATCH 3/3] dt-bindings: panel: Add bindings for MRB2801

2020-11-17 Thread mdurnev
From: Mikhail Durnev 

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 
---
 .../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 000..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>;
+   };
-- 
2.7.4