Re: [PATCH v1 5/5] tinydrm: add winstar wg160160 driver

2018-08-11 Thread Sam Ravnborg
Hi Noralf.

On Tue, Aug 07, 2018 at 07:35:30PM +0200, Noralf Trønnes wrote:
> 
> Den 02.08.2018 21.45, skrev Sam Ravnborg:
> >Add driver for the winstar wg160160 display.
> >The driver utilises pardata-dbi that
> >again utilise the pardata subsystem.
> >
> >Signed-off-by: Sam Ravnborg 
> >---
> >  MAINTAINERS|   5 +
> >  drivers/gpu/drm/tinydrm/Kconfig|  10 ++
> >  drivers/gpu/drm/tinydrm/Makefile   |   1 +
> >  drivers/gpu/drm/tinydrm/wg160160.c | 298 
> > +
> >  4 files changed, 314 insertions(+)
> >  create mode 100644 drivers/gpu/drm/tinydrm/wg160160.c
> >
> 
> [...]
> 
> >+
> >+/**
> >+ * write_reg - Write instruction on parallel bus to controller
> >+ *
> >+ * Check BUSY flag and write instruction
> >+ *
> >+ * @pdd: pardata data
> >+ * @reg: The register to write
> >+ * @value: The value of the register
> >+ *
> >+ * Returns:
> >+ * Zero on success, negative error code on failure
> >+ */
> >+int write_reg(struct pardata_data *pdd, unsigned int reg, unsigned int 
> >value)
> >+{
> >+int ins[PIN_NUM];
> >+int val[PIN_NUM];
> >+int i;
> >+
> >+for (i = 0; i < PIN_NUM; i++)
> >+ins[PIN_DB0 + i] = !!BIT(reg);
> >+
> >+for (i = 0; i < PIN_NUM; i++)
> >+val[PIN_DB0 + i] = !!(value & BIT(i));
> >+
> >+gpiod_set_value_cansleep(pdd->bus->pin_rs, 1);
> >+gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, ins);
> >+wait_busy(pdd);
> >+pardata_strobe_write(pdd);
> >+
> >+gpiod_set_value_cansleep(pdd->bus->pin_rs, 0);
> >+gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, val);
> >+wait_busy(pdd);
> >+pardata_strobe_write(pdd);
> >+
> >+return 0;
> >+}
> 
> If this controller has normal registers, you could do a regmap
> implementation for pardata: drivers/base/regmap.

If I understand you correct then you suggest to add a regmap implementation
on top of the registers replacing the current gpio support?

So we in regmap can optimize access to the registers better.
Or did you have something else in mind?

As speed is not the main challenge here I will likely wait with this
and continue using gpio.

Sam
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v1 5/5] tinydrm: add winstar wg160160 driver

2018-08-08 Thread Noralf Trønnes


Den 08.08.2018 10.32, skrev Sam Ravnborg:

Hi Noralf.

On Tue, Aug 07, 2018 at 07:35:30PM +0200, Noralf Trønnes wrote:

Den 02.08.2018 21.45, skrev Sam Ravnborg:

Add driver for the winstar wg160160 display.
The driver utilises pardata-dbi that
again utilise the pardata subsystem.

Signed-off-by: Sam Ravnborg 
---
  MAINTAINERS|   5 +
  drivers/gpu/drm/tinydrm/Kconfig|  10 ++
  drivers/gpu/drm/tinydrm/Makefile   |   1 +
  drivers/gpu/drm/tinydrm/wg160160.c | 298 +
  4 files changed, 314 insertions(+)
  create mode 100644 drivers/gpu/drm/tinydrm/wg160160.c


[...]


+
+/**
+ * write_reg - Write instruction on parallel bus to controller
+ *
+ * Check BUSY flag and write instruction
+ *
+ * @pdd: pardata data
+ * @reg: The register to write
+ * @value: The value of the register
+ *
+ * Returns:
+ * Zero on success, negative error code on failure
+ */
+int write_reg(struct pardata_data *pdd, unsigned int reg, unsigned int value)
+{
+   int ins[PIN_NUM];
+   int val[PIN_NUM];
+   int i;
+
+   for (i = 0; i < PIN_NUM; i++)
+   ins[PIN_DB0 + i] = !!BIT(reg);
+
+   for (i = 0; i < PIN_NUM; i++)
+   val[PIN_DB0 + i] = !!(value & BIT(i));
+
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 1);
+   gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, ins);
+   wait_busy(pdd);
+   pardata_strobe_write(pdd);
+
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 0);
+   gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, val);
+   wait_busy(pdd);
+   pardata_strobe_write(pdd);
+
+   return 0;
+}

If this controller has normal registers, you could do a regmap
implementation for pardata: drivers/base/regmap.

If I understand you correct then you suggest to add a regmap implementation
on top of the registers replacing the current gpio support?

So we in regmap can optimize access to the registers better.
Or did you have something else in mind?


I was thinking of a regmap-pardata.c like drivers/base/regmap/regmap-i2c.c.
It's not much code an we would avoid having generic register access
functions in DRM. It's not about speed or caching, but just to try and
put code where it logically belongs.

Here is one experiment where I have created a regmap on a 8080 bus:
https://github.com/notro/tinydrm/blob/master/tinydrm-regmap.c
Used here: https://github.com/notro/tinydrm/blob/master/fb_ili9325.c

I don't advocate this particular approach, I mention it just as an
example of using regmap in a tinydrm driver.

Noralf.


As speed is not the main challenge here I will likely wait with this
and continue using gpio.

Sam


___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v1 5/5] tinydrm: add winstar wg160160 driver

2018-08-07 Thread Noralf Trønnes


Den 02.08.2018 21.45, skrev Sam Ravnborg:

Add driver for the winstar wg160160 display.
The driver utilises pardata-dbi that
again utilise the pardata subsystem.

Signed-off-by: Sam Ravnborg 
---
  MAINTAINERS|   5 +
  drivers/gpu/drm/tinydrm/Kconfig|  10 ++
  drivers/gpu/drm/tinydrm/Makefile   |   1 +
  drivers/gpu/drm/tinydrm/wg160160.c | 298 +
  4 files changed, 314 insertions(+)
  create mode 100644 drivers/gpu/drm/tinydrm/wg160160.c



[...]


+
+/**
+ * write_reg - Write instruction on parallel bus to controller
+ *
+ * Check BUSY flag and write instruction
+ *
+ * @pdd: pardata data
+ * @reg: The register to write
+ * @value: The value of the register
+ *
+ * Returns:
+ * Zero on success, negative error code on failure
+ */
+int write_reg(struct pardata_data *pdd, unsigned int reg, unsigned int value)
+{
+   int ins[PIN_NUM];
+   int val[PIN_NUM];
+   int i;
+
+   for (i = 0; i < PIN_NUM; i++)
+   ins[PIN_DB0 + i] = !!BIT(reg);
+
+   for (i = 0; i < PIN_NUM; i++)
+   val[PIN_DB0 + i] = !!(value & BIT(i));
+
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 1);
+   gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, ins);
+   wait_busy(pdd);
+   pardata_strobe_write(pdd);
+
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 0);
+   gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, val);
+   wait_busy(pdd);
+   pardata_strobe_write(pdd);
+
+   return 0;
+}


If this controller has normal registers, you could do a regmap
implementation for pardata: drivers/base/regmap.

Noralf.


+
+/**
+ * write_buf - write buffer on parallel bus to controller
+ *
+ * @pdd: pardata data
+ * @offset: offset into display RAM
+ * @data: pointer to data to write
+ * @len: number of bytes to write
+ *
+ * Returns:
+ * Zero on success, negative error code on failure
+ */
+int write_buf(struct pardata_data *pdd, u8 offset, u8 *data, size_t len)
+{
+   int ins[PIN_NUM];
+   int val[PIN_NUM];
+   int bit;
+   int i;
+
+   /* Setup address */
+   write_reg(pdd, WG160160_ADDRSL_REG, offset & 0xff);
+   write_reg(pdd, WG160160_ADDRSL_REG, (offset >> 8) & 0xff);
+
+   /* prepare to write data */
+   for (i = 0; i < PIN_NUM; i++)
+   ins[PIN_DB0 + i] = !!(WG160160_WRITE_REG & BIT(i));
+
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 1);
+   gpiod_set_array_value_cansleep(PIN_NUM, pdd->bus->data_pins->desc, ins);
+   wait_busy(pdd);
+   pardata_strobe_write(pdd);
+
+   /* Write data byte - by byte */
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 0);
+
+   for (i = offset; i < (offset + len); i++) {
+   for (bit = 0; bit < PIN_NUM; bit++)
+   val[PIN_DB0 + bit] = !!(data[i] & BIT(bit));
+
+   gpiod_set_array_value_cansleep(PIN_NUM,
+  pdd->bus->data_pins->desc,
+  val);
+   wait_busy(pdd);
+   pardata_strobe_write(pdd);
+   }
+
+   return 0;
+}


___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v1 5/5] tinydrm: add winstar wg160160 driver

2018-08-07 Thread Sam Ravnborg
On Mon, Aug 06, 2018 at 12:15:48PM +0300, Dan Carpenter wrote:
> Hi Sam,
> 
> I love your patch! Perhaps something to improve:
> 
> url:
> https://github.com/0day-ci/linux/commits/Sam-Ravnborg/dt-bindings-add-parallel-data-bus-pardata/20180803-090135
> 
> smatch warnings:
> drivers/gpu/drm/tinydrm/wg160160.c:145 write_buf() warn: right shifting more 
> than type allows 8 vs 8
> include/drm/tinydrm/pardata-dbi.h:165 pardata_write_buf() error: we 
> previously assumed 'pdd' could be null (see line 162)
> 
> # 
> https://github.com/0day-ci/linux/commit/9fcebca9e208029e06eea5e4858c1055132f06b6
> git remote add linux-review https://github.com/0day-ci/linux
> git remote update linux-review
> git checkout 9fcebca9e208029e06eea5e4858c1055132f06b6
> vim +145 drivers/gpu/drm/tinydrm/wg160160.c
> 
> 9fcebca9 Sam Ravnborg 2018-08-02  124  
> 9fcebca9 Sam Ravnborg 2018-08-02  125  /**
> 9fcebca9 Sam Ravnborg 2018-08-02  126   * write_buf - write buffer on 
> parallel bus to controller
> 9fcebca9 Sam Ravnborg 2018-08-02  127   *
> 9fcebca9 Sam Ravnborg 2018-08-02  128   * @pdd: pardata data
> 9fcebca9 Sam Ravnborg 2018-08-02  129   * @offset: offset into display RAM
> 9fcebca9 Sam Ravnborg 2018-08-02  130   * @data: pointer to data to write
> 9fcebca9 Sam Ravnborg 2018-08-02  131   * @len: number of bytes to write
> 9fcebca9 Sam Ravnborg 2018-08-02  132   *
> 9fcebca9 Sam Ravnborg 2018-08-02  133   * Returns:
> 9fcebca9 Sam Ravnborg 2018-08-02  134   * Zero on success, negative error 
> code on failure
> 9fcebca9 Sam Ravnborg 2018-08-02  135   */
> 9fcebca9 Sam Ravnborg 2018-08-02  136  int write_buf(struct pardata_data 
> *pdd, u8 offset, u8 *data, size_t len)
> 9fcebca9 Sam Ravnborg 2018-08-02  137  {
> 9fcebca9 Sam Ravnborg 2018-08-02  138 int ins[PIN_NUM];
> 9fcebca9 Sam Ravnborg 2018-08-02  139 int val[PIN_NUM];
> 9fcebca9 Sam Ravnborg 2018-08-02  140 int bit;
> 9fcebca9 Sam Ravnborg 2018-08-02  141 int i;
> 9fcebca9 Sam Ravnborg 2018-08-02  142  
> 9fcebca9 Sam Ravnborg 2018-08-02  143 /* Setup address */
> 9fcebca9 Sam Ravnborg 2018-08-02  144 write_reg(pdd, 
> WG160160_ADDRSL_REG, offset & 0xff);
> 9fcebca9 Sam Ravnborg 2018-08-02 @145 write_reg(pdd, 
> WG160160_ADDRSL_REG, (offset >> 8) & 0xff);
> 
> 
> Probably this is fine.  I don't know.  If so then feel free to ignore
> the warning.

Thanks!
I will fix both issues in v2.

Sam
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH v1 5/5] tinydrm: add winstar wg160160 driver

2018-08-06 Thread Dan Carpenter
Hi Sam,

I love your patch! Perhaps something to improve:

url:
https://github.com/0day-ci/linux/commits/Sam-Ravnborg/dt-bindings-add-parallel-data-bus-pardata/20180803-090135

smatch warnings:
drivers/gpu/drm/tinydrm/wg160160.c:145 write_buf() warn: right shifting more 
than type allows 8 vs 8
include/drm/tinydrm/pardata-dbi.h:165 pardata_write_buf() error: we previously 
assumed 'pdd' could be null (see line 162)

# 
https://github.com/0day-ci/linux/commit/9fcebca9e208029e06eea5e4858c1055132f06b6
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout 9fcebca9e208029e06eea5e4858c1055132f06b6
vim +145 drivers/gpu/drm/tinydrm/wg160160.c

9fcebca9 Sam Ravnborg 2018-08-02  124  
9fcebca9 Sam Ravnborg 2018-08-02  125  /**
9fcebca9 Sam Ravnborg 2018-08-02  126   * write_buf - write buffer on parallel 
bus to controller
9fcebca9 Sam Ravnborg 2018-08-02  127   *
9fcebca9 Sam Ravnborg 2018-08-02  128   * @pdd: pardata data
9fcebca9 Sam Ravnborg 2018-08-02  129   * @offset: offset into display RAM
9fcebca9 Sam Ravnborg 2018-08-02  130   * @data: pointer to data to write
9fcebca9 Sam Ravnborg 2018-08-02  131   * @len: number of bytes to write
9fcebca9 Sam Ravnborg 2018-08-02  132   *
9fcebca9 Sam Ravnborg 2018-08-02  133   * Returns:
9fcebca9 Sam Ravnborg 2018-08-02  134   * Zero on success, negative error code 
on failure
9fcebca9 Sam Ravnborg 2018-08-02  135   */
9fcebca9 Sam Ravnborg 2018-08-02  136  int write_buf(struct pardata_data *pdd, 
u8 offset, u8 *data, size_t len)
9fcebca9 Sam Ravnborg 2018-08-02  137  {
9fcebca9 Sam Ravnborg 2018-08-02  138   int ins[PIN_NUM];
9fcebca9 Sam Ravnborg 2018-08-02  139   int val[PIN_NUM];
9fcebca9 Sam Ravnborg 2018-08-02  140   int bit;
9fcebca9 Sam Ravnborg 2018-08-02  141   int i;
9fcebca9 Sam Ravnborg 2018-08-02  142  
9fcebca9 Sam Ravnborg 2018-08-02  143   /* Setup address */
9fcebca9 Sam Ravnborg 2018-08-02  144   write_reg(pdd, WG160160_ADDRSL_REG, 
offset & 0xff);
9fcebca9 Sam Ravnborg 2018-08-02 @145   write_reg(pdd, WG160160_ADDRSL_REG, 
(offset >> 8) & 0xff);


Probably this is fine.  I don't know.  If so then feel free to ignore
the warning.

9fcebca9 Sam Ravnborg 2018-08-02  146  
9fcebca9 Sam Ravnborg 2018-08-02  147   /* prepare to write data */
9fcebca9 Sam Ravnborg 2018-08-02  148   for (i = 0; i < PIN_NUM; i++)
9fcebca9 Sam Ravnborg 2018-08-02  149   ins[PIN_DB0 + i] = 
!!(WG160160_WRITE_REG & BIT(i));
9fcebca9 Sam Ravnborg 2018-08-02  150  
9fcebca9 Sam Ravnborg 2018-08-02  151   
gpiod_set_value_cansleep(pdd->bus->pin_rs, 1);
9fcebca9 Sam Ravnborg 2018-08-02  152   gpiod_set_array_value_cansleep(PIN_NUM, 
pdd->bus->data_pins->desc, ins);
9fcebca9 Sam Ravnborg 2018-08-02  153   wait_busy(pdd);
9fcebca9 Sam Ravnborg 2018-08-02  154   pardata_strobe_write(pdd);
9fcebca9 Sam Ravnborg 2018-08-02  155  
9fcebca9 Sam Ravnborg 2018-08-02  156   /* Write data byte - by byte */
9fcebca9 Sam Ravnborg 2018-08-02  157   
gpiod_set_value_cansleep(pdd->bus->pin_rs, 0);
9fcebca9 Sam Ravnborg 2018-08-02  158  
9fcebca9 Sam Ravnborg 2018-08-02  159   for (i = offset; i < (offset + len); 
i++) {
9fcebca9 Sam Ravnborg 2018-08-02  160   for (bit = 0; bit < PIN_NUM; 
bit++)
9fcebca9 Sam Ravnborg 2018-08-02  161   val[PIN_DB0 + bit] = 
!!(data[i] & BIT(bit));
9fcebca9 Sam Ravnborg 2018-08-02  162  
9fcebca9 Sam Ravnborg 2018-08-02  163   
gpiod_set_array_value_cansleep(PIN_NUM,
9fcebca9 Sam Ravnborg 2018-08-02  164  
pdd->bus->data_pins->desc,
9fcebca9 Sam Ravnborg 2018-08-02  165  
val);
9fcebca9 Sam Ravnborg 2018-08-02  166   wait_busy(pdd);
9fcebca9 Sam Ravnborg 2018-08-02  167   pardata_strobe_write(pdd);
9fcebca9 Sam Ravnborg 2018-08-02  168   }
9fcebca9 Sam Ravnborg 2018-08-02  169  
9fcebca9 Sam Ravnborg 2018-08-02  170   return 0;
9fcebca9 Sam Ravnborg 2018-08-02  171  }
9fcebca9 Sam Ravnborg 2018-08-02  172  

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v1 5/5] tinydrm: add winstar wg160160 driver

2018-08-03 Thread Sam Ravnborg
Add driver for the winstar wg160160 display.
The driver utilises pardata-dbi that
again utilise the pardata subsystem.

Signed-off-by: Sam Ravnborg 
---
 MAINTAINERS|   5 +
 drivers/gpu/drm/tinydrm/Kconfig|  10 ++
 drivers/gpu/drm/tinydrm/Makefile   |   1 +
 drivers/gpu/drm/tinydrm/wg160160.c | 298 +
 4 files changed, 314 insertions(+)
 create mode 100644 drivers/gpu/drm/tinydrm/wg160160.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4ba7ff7c3e46..d77e53041395 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15501,6 +15501,11 @@ L: linux-watch...@vger.kernel.org
 S: Maintained
 F: drivers/watchdog/ebc-c384_wdt.c
 
+WINSTAR WG160160 DRIVER
+M: Sam Ravnborg 
+S: Maintained
+F: drivers/gpu/drm/tinydrm/wg160160.c
+
 WINSYSTEMS WS16C48 GPIO DRIVER
 M: William Breathitt Gray 
 L: linux-g...@vger.kernel.org
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig
index 435de2f8d8f5..40315680c0bc 100644
--- a/drivers/gpu/drm/tinydrm/Kconfig
+++ b/drivers/gpu/drm/tinydrm/Kconfig
@@ -65,3 +65,13 @@ config TINYDRM_ST7735R
  * JD-T18003-T01 1.8" 128x160 TFT
 
  If M is selected the module will be called st7735r.
+
+config TINYDRM_WG160160
+   tristate "DRM support for Winstar WG160160"
+   depends on DRM_TINYDRM && PARDATA
+   select TINYDRM_PARDATA_DBI
+   help
+ DRM driver for Winstar WG160106.
+ See 
https://www.winstar.com.tw/products/graphic-lcd-display-module/lcd-graphics.html
+
+ If M is selected the module will be named wg160160.
diff --git a/drivers/gpu/drm/tinydrm/Makefile b/drivers/gpu/drm/tinydrm/Makefile
index 0b52df08b0a4..849891fe40cb 100644
--- a/drivers/gpu/drm/tinydrm/Makefile
+++ b/drivers/gpu/drm/tinydrm/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_TINYDRM_MI0283QT)+= mi0283qt.o
 obj-$(CONFIG_TINYDRM_REPAPER)  += repaper.o
 obj-$(CONFIG_TINYDRM_ST7586)   += st7586.o
 obj-$(CONFIG_TINYDRM_ST7735R)  += st7735r.o
+obj-$(CONFIG_TINYDRM_WG160160) += wg160160.o
diff --git a/drivers/gpu/drm/tinydrm/wg160160.c 
b/drivers/gpu/drm/tinydrm/wg160160.c
new file mode 100644
index ..5477c8ed5599
--- /dev/null
+++ b/drivers/gpu/drm/tinydrm/wg160160.c
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DRM driver for Winstar WG160160 panels
+ *
+ * Copyright 2018 Sam Ravnborg 
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#define WG160160_MODE_REG  0x00
+#define MODE_GRAPHIC_DISP_OFF  0x12
+#define MODE_GRAPHIC_DISP_ON   0x32
+
+#define WG160160_PITCH_REG 0x01
+#define WG160160_WIDTH_REG 0x02
+#define WG160160_DUTY_REG  0x03
+#define WG160160_CURSORPOS_REG 0x04
+#define WG160160_ADDRSL_REG0x08 /* Start lower address */
+#define WG160160_ADDRSU_REG0x09 /* Start upper address */
+#define WG160160_WRITE_REG 0x0c /* Write byte, inc cursor */
+#define WG160160_READ_REG  0x0d /* Read byte, inc cursor */
+
+#define WG160160_BUSY_MASK 0x80
+#define BUSY_ACTIVE1
+#define BUSY_INACTIVE  0
+
+/**
+ * busy_status -read status of busy flag
+ *
+ * @pdd: pardata data
+ *
+ * returns: true if busy, false if not
+ */
+static bool busy_status(struct pardata_data *pdd)
+{
+   int data;
+
+   gpiod_set_value_cansleep(pdd->bus->pin_rs, 1);
+   gpiod_set_value_cansleep(pdd->bus->pin_readwrite, 1);
+   gpiod_set_value_cansleep(pdd->pin_cs, 0);
+   /* min 90 nsec from cs/rs/rw to e */
+   udelay(1);
+   gpiod_set_value_cansleep(pdd->bus->pin_enable, 1);
+   /* data setup time 220 ns*/
+   udelay(2);
+
+   data = gpiod_get_value(pdd->bus->data_pins->desc[PIN_DB7]);
+
+   gpiod_set_value_cansleep(pdd->bus->pin_enable, 0);
+   /* data hold time 20 ns */
+   udelay(1);
+   gpiod_set_value_cansleep(pdd->pin_cs, 1);
+
+   return data == 1;
+}
+
+/**
+ * wait_busy - wait until controller is no longer busy
+ *
+ * Logs an ERROR once if we fail to see a not BUSY condition
+ *
+ * @pdd: pardata_data
+ */
+static void wait_busy(struct pardata_data *pdd)
+{
+   int i;
+
+   i = 0;
+
+   while (busy_status(pdd) && i++ < 10)
+   udelay(1);
+
+   if (i >= 10)
+   DRM_DEV_ERROR_RATELIMITED(>pddev->dev,
+ "Timeout waiting for BUSY=0\n");
+}
+
+/**
+ * write_reg - Write instruction on parallel bus to controller
+ *
+ * Check BUSY flag and write instruction
+ *
+ * @pdd: pardata data
+ * @reg: The register to write
+ * @value: The value of the register
+ *
+ * Returns:
+ * Zero on success, negative error code on failure
+ */
+int write_reg(struct pardata_data *pdd, unsigned int reg, unsigned int value)
+{
+   int ins[PIN_NUM];
+   int