[PATCH] auxdisplay: panel: Remove redundant charlcd_ops structures

2020-11-16 Thread poeschel
From: Lars Poeschel 

The three struct charlcd_ops contain the same data, so we only need one
of this structures. The other two are removed.

Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/panel.c | 42 --
 1 file changed, 4 insertions(+), 38 deletions(-)

diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 36848e464d1f..ff5755ee5694 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -808,41 +808,7 @@ static void lcd_write_data_tilcd(struct hd44780_common 
*hdc, int data)
spin_unlock_irq(_lock);
 }
 
-static const struct charlcd_ops charlcd_serial_ops = {
-   .backlight  = lcd_backlight,
-   .print  = hd44780_common_print,
-   .gotoxy = hd44780_common_gotoxy,
-   .home   = hd44780_common_home,
-   .clear_display  = hd44780_common_clear_display,
-   .init_display   = hd44780_common_init_display,
-   .shift_cursor   = hd44780_common_shift_cursor,
-   .shift_display  = hd44780_common_shift_display,
-   .display= hd44780_common_display,
-   .cursor = hd44780_common_cursor,
-   .blink  = hd44780_common_blink,
-   .fontsize   = hd44780_common_fontsize,
-   .lines  = hd44780_common_lines,
-   .redefine_char  = hd44780_common_redefine_char,
-};
-
-static const struct charlcd_ops charlcd_parallel_ops = {
-   .backlight  = lcd_backlight,
-   .print  = hd44780_common_print,
-   .gotoxy = hd44780_common_gotoxy,
-   .home   = hd44780_common_home,
-   .clear_display  = hd44780_common_clear_display,
-   .init_display   = hd44780_common_init_display,
-   .shift_cursor   = hd44780_common_shift_cursor,
-   .shift_display  = hd44780_common_shift_display,
-   .display= hd44780_common_display,
-   .cursor = hd44780_common_cursor,
-   .blink  = hd44780_common_blink,
-   .fontsize   = hd44780_common_fontsize,
-   .lines  = hd44780_common_lines,
-   .redefine_char  = hd44780_common_redefine_char,
-};
-
-static const struct charlcd_ops charlcd_tilcd_ops = {
+static const struct charlcd_ops charlcd_ops = {
.backlight  = lcd_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
@@ -984,7 +950,7 @@ static void lcd_init(void)
charlcd->height = DEFAULT_LCD_HEIGHT;
 
if (lcd.proto == LCD_PROTO_SERIAL) {/* SERIAL */
-   charlcd->ops = _serial_ops;
+   charlcd->ops = _ops;
hdc->write_data = lcd_write_data_s;
hdc->write_cmd = lcd_write_cmd_s;
 
@@ -994,7 +960,7 @@ static void lcd_init(void)
lcd.pins.da = DEFAULT_LCD_PIN_SDA;
 
} else if (lcd.proto == LCD_PROTO_PARALLEL) {   /* PARALLEL */
-   charlcd->ops = _parallel_ops;
+   charlcd->ops = _ops;
hdc->write_data = lcd_write_data_p8;
hdc->write_cmd = lcd_write_cmd_p8;
 
@@ -1005,7 +971,7 @@ static void lcd_init(void)
if (lcd.pins.rw == PIN_NOT_SET)
lcd.pins.rw = DEFAULT_LCD_PIN_RW;
} else {
-   charlcd->ops = _tilcd_ops;
+   charlcd->ops = _ops;
hdc->write_data = lcd_write_data_tilcd;
hdc->write_cmd = lcd_write_cmd_tilcd;
}
-- 
2.29.2



[PATCH] auxdisplay: panel: Fix missing print function pointer

2020-11-16 Thread poeschel
From: Lars Poeschel 

charlcd drivers need to provide some print function to charlcd. For
hd44780 based panel driver this function was missing. We provide the
generic hd44780_common_print function which should be suitable.

Fixes: b26deabb1d915fe87d395081bbd3058b938dee89 ("auxdisplay: 
hd44780_common_print")
Reported-by: kernel test robot 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/panel.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index e07fadac281d..36848e464d1f 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -810,6 +810,7 @@ static void lcd_write_data_tilcd(struct hd44780_common 
*hdc, int data)
 
 static const struct charlcd_ops charlcd_serial_ops = {
.backlight  = lcd_backlight,
+   .print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
.clear_display  = hd44780_common_clear_display,
@@ -826,6 +827,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 
 static const struct charlcd_ops charlcd_parallel_ops = {
.backlight  = lcd_backlight,
+   .print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
.clear_display  = hd44780_common_clear_display,
@@ -842,6 +844,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
.backlight  = lcd_backlight,
+   .print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
.clear_display  = hd44780_common_clear_display,
-- 
2.29.2



Re: [LKP] Re: [auxdisplay] b26deabb1d: BUG:kernel_NULL_pointer_dereference,address

2020-11-16 Thread Lars Poeschel
On Thu, Nov 12, 2020 at 01:29:31PM +, Sang, Oliver wrote:
> 
> 
> > -Original Message-
> > From: Lars Poeschel 
> > Sent: Monday, November 9, 2020 8:40 PM
> > To: Sang, Oliver 
> > Cc: Miguel Ojeda ; lkp ; Willy Tarreau
> > ; LKML ; Linux Memory
> > Management List ; l...@lists.01.org
> > Subject: [LKP] Re: [auxdisplay] b26deabb1d:
> > BUG:kernel_NULL_pointer_dereference,address
> > 
> > Hi!
> > 
> > And thanks for your report.
> > 
> > On Mon, Nov 09, 2020 at 02:29:34PM +0800, kernel test robot wrote:
> > 
> > > To reproduce:
> > >
> > > # build kernel
> > >   cd linux
> > >   cp config-5.10.0-rc2-8-gb26deabb1d91 .config
> > >   make HOSTCC=gcc-9 CC=gcc-9 ARCH=i386 olddefconfig prepare
> > > modules_prepare bzImage
> > >
> > > git clone https://github.com/intel/lkp-tests.git
> > > cd lkp-tests
> > > bin/lkp qemu -k  job-script # job-script is attached
> > > in this email
> > 
> > Trying to reproduce your issue:
> > 
> > LANG=C bin/lkp qemu -k ~/projekte/linux-stable/arch/x86_64/boot/bzImage
> > /tmp/job-script
> > result_root: /home/larsi/.lkp//result/trinity/300s/vm-snb-i386/yocto-i386-
> > minimal-20190520.cgz/i386-randconfig-a002-20201105/gcc-
> > 9/b26deabb1d915fe87d395081bbd3058b938dee89/6
> > downloading initrds ...
> > /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8
> > https://download.01.org/0day-ci/lkp-qemu/osimage/yocto/yocto-i386-
> > minimal-20190520.cgz -N -P /home/larsi/.lkp/cache/osimage/yocto
> > 17916 blocks
> > /usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8
> > https://download.01.org/0day-ci/lkp-qemu/osimage/pkg/yocto-i386-minimal-
> > 20190520.cgz/trinity-i386.cgz -N -P 
> > /home/larsi/.lkp/cache/osimage/pkg/yocto-
> > i386-minimal-20190520.cgz
> > Failed to download osimage/pkg/yocto-i386-minimal-20190520.cgz/trinity-
> > i386.cgz
> > 
> > It seems, that the trinity-i386.cgz file is not downloadable. Using a 
> > webbrowser I
> > can see an empty directory.
> > Can you help please ?
> 
> sorry for this. just uploaded. 
> https://download.01.org/0day-ci/lkp-qemu/osimage/pkg/yocto-i386-minimal-20190520.cgz/trinity-i386.cgz
> could you try again?

It is working now and I can reproduce the error.
Thank you!


Re: [auxdisplay] b26deabb1d: BUG:kernel_NULL_pointer_dereference,address

2020-11-09 Thread Lars Poeschel
Hi!

And thanks for your report.

On Mon, Nov 09, 2020 at 02:29:34PM +0800, kernel test robot wrote:

> To reproduce:
> 
> # build kernel
>   cd linux
>   cp config-5.10.0-rc2-8-gb26deabb1d91 .config
>   make HOSTCC=gcc-9 CC=gcc-9 ARCH=i386 olddefconfig prepare 
> modules_prepare bzImage
> 
> git clone https://github.com/intel/lkp-tests.git
> cd lkp-tests
> bin/lkp qemu -k  job-script # job-script is attached in this 
> email

Trying to reproduce your issue:

LANG=C bin/lkp qemu -k ~/projekte/linux-stable/arch/x86_64/boot/bzImage 
/tmp/job-script
result_root: 
/home/larsi/.lkp//result/trinity/300s/vm-snb-i386/yocto-i386-minimal-20190520.cgz/i386-randconfig-a002-20201105/gcc-9/b26deabb1d915fe87d395081bbd3058b938dee89/6
downloading initrds ...
/usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 
https://download.01.org/0day-ci/lkp-qemu/osimage/yocto/yocto-i386-minimal-20190520.cgz
 -N -P /home/larsi/.lkp/cache/osimage/yocto
17916 blocks
/usr/bin/wget -q --timeout=1800 --tries=1 --local-encoding=UTF-8 
https://download.01.org/0day-ci/lkp-qemu/osimage/pkg/yocto-i386-minimal-20190520.cgz/trinity-i386.cgz
 -N -P /home/larsi/.lkp/cache/osimage/pkg/yocto-i386-minimal-20190520.cgz
Failed to download osimage/pkg/yocto-i386-minimal-20190520.cgz/trinity-i386.cgz

It seems, that the trinity-i386.cgz file is not downloadable. Using a
webbrowser I can see an empty directory.
Can you help please ?

Thanks,
Lars


Re: [PATCH] auxdisplay: fix use after free in lcd2s_i2c_remove()

2020-11-09 Thread Lars Poeschel
On Fri, Nov 06, 2020 at 10:24:15PM +0300, Dan Carpenter wrote:
> The kfree() needs to be moved down a line to prevent a use after free.
> 
> Fixes: 8c9108d014c5 ("auxdisplay: add a driver for lcd2s character display")
> Signed-off-by: Dan Carpenter 
> ---
>  drivers/auxdisplay/lcd2s.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
> index cfa5f86deeef..3eb7f04db6cb 100644
> --- a/drivers/auxdisplay/lcd2s.c
> +++ b/drivers/auxdisplay/lcd2s.c
> @@ -348,8 +348,8 @@ static int lcd2s_i2c_remove(struct i2c_client *i2c)
>  {
>   struct lcd2s_data *lcd2s = i2c_get_clientdata(i2c);
>  
> - kfree(lcd2s->charlcd);
>   charlcd_unregister(lcd2s->charlcd);
> + kfree(lcd2s->charlcd);
>   return 0;
>  }

Reviewed-by: Lars Pöschel 

Thanks,
Lars


[PATCH] auxdisplay: hd44780_common: Fix build error

2020-11-09 Thread poeschel
From: Lars Poeschel 

When building the hd44780_common driver without a driver that actually
uses it like panel or hd44780 you got a build error, because
hd44780_common uses charlcd, but did not select it. It's users did
select it.
This is fixed now. hd4478_common now selects charlcd in Kconfig and
panel and hd44780 do not. They only select hd44780_common.

Reported-by: Randy Dunlap 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/Kconfig | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index a69623124a26..a2b59b84bb88 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -27,6 +27,7 @@ config CHARLCD
 
 config HD44780_COMMON
tristate "Common functions for HD44780 (and compatibles) LCD displays" 
if COMPILE_TEST
+   select CHARLCD
help
  This is a module with the common symbols for HD44780 (and compatibles)
  displays. This is the code that multiple other modules use. It is not
@@ -37,7 +38,6 @@ config HD44780_COMMON
 config HD44780
tristate "HD44780 Character LCD support"
depends on GPIOLIB || COMPILE_TEST
-   select CHARLCD
select HD44780_COMMON
help
  Enable support for Character LCDs using a HD44780 controller.
@@ -196,7 +196,6 @@ config ARM_CHARLCD
 menuconfig PARPORT_PANEL
tristate "Parallel port LCD/Keypad Panel support"
depends on PARPORT
-   select CHARLCD
select HD44780_COMMON
help
  Say Y here if you have an HD44780 or KS-0074 LCD connected to your
-- 
2.28.0



Re: [PATCH v6 00/25] Make charlcd device independent

2020-11-06 Thread Lars Poeschel
On Wed, Nov 04, 2020 at 02:30:04PM +0100, Miguel Ojeda wrote:
> Thanks a lot for all the work, Lars. Queued in -next.

I got an email [1] with a report about a build failure in
hd44780_common. The fix is simple but I don't know the process from here
on. Should I post a v7 of the whole patchset or only a follow-up patch
for the fix ?

Regards,
Lars

[1]: 
https://lore.kernel.org/linux-next/77c23d41-b652-bd08-12ef-6d3403f0a...@infradead.org/T/#u


[PATCH v6 11/25] auxdisplay: Move clear_display to hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

This moves the clear_display function from charlcd to hd44780_common.
This is one more step to make charlcd independent from device specific
code. The two hd44780 drivers use the new function from hd44780_common
and charlcd calls this function through its function pointer in its ops
structure.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 22 ++
 drivers/auxdisplay/charlcd.h|  4 
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 21 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 44dd6e02eaf9..fc0daf4987d5 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -34,8 +34,6 @@
 #define LCD_FLAG_L 0x0080  /* Backlight enabled */
 
 /* LCD commands */
-#define LCD_CMD_DISPLAY_CLEAR  0x01/* Clear entire display */
-
 #define LCD_CMD_ENTRY_MODE 0x04/* Set entry mode */
 #define LCD_CMD_CURSOR_INC 0x02/* Increment cursor */
 
@@ -178,18 +176,6 @@ static void charlcd_clear_fast(struct charlcd *lcd)
charlcd_home(lcd);
 }
 
-/* clears the display and resets X/Y */
-static void charlcd_clear_display(struct charlcd *lcd)
-{
-   struct hd44780_common *hdc = lcd->drvdata;
-
-   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   /* we must wait a few milliseconds (15) */
-   long_sleep(15);
-}
-
 static int charlcd_init_display(struct charlcd *lcd)
 {
void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
@@ -254,7 +240,9 @@ static int charlcd_init_display(struct charlcd *lcd)
/* entry mode set : increment, cursor shifting */
hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
 
-   charlcd_clear_display(lcd);
+   lcd->ops->clear_display(lcd);
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
return 0;
 }
 
@@ -670,8 +658,10 @@ static int charlcd_open(struct inode *inode, struct file 
*file)
goto fail;
 
if (priv->must_clear) {
-   charlcd_clear_display(>lcd);
+   priv->lcd.ops->clear_display(>lcd);
priv->must_clear = false;
+   priv->lcd.addr.x = 0;
+   priv->lcd.addr.y = 0;
}
return nonseekable_open(inode, file);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 236fd0e9e8ab..a6c32c4d1aac 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -43,6 +43,9 @@ struct charlcd {
  * previously set in addr.x and addr.y by charlcd.
  * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
  * charlcd prior to calling this function.
+ * @clear_display: Again clear the whole display, set the cursor to 0, 0. The
+ * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
+ * function.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -50,6 +53,7 @@ struct charlcd_ops {
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
int (*home)(struct charlcd *lcd);
+   int (*clear_display)(struct charlcd *lcd);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index b0893ea49165..40ea6d25dbe1 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -129,6 +129,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
+   .clear_display  = hd44780_common_clear_display,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -175,6 +176,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
+   .clear_display  = hd44780_common_clear_display,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index ea62beada9d8..2f7d55668eb4 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -1,13 +1,22 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 #include 
+#include 
 #include 
 
 #include "charlcd.h"
 #include "hd44780_common.h"
 
 /* LCD commands */
+#define LCD_CMD_DISPLAY_CLEAR  0x01/* Clear entire display */
+
 #define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
 
+/* sleeps that many milliseconds with a reschedule */
+s

[PATCH v6 04/25] auxdisplay: Move ifwidth to struct hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

Move struct charlcd member ifwidth to our new struct hd44780_common.
ifwidth is hd44780 device specific and is used by two drivers at the
moment, so we move it to a common place, where both can use this.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 12 ++--
 drivers/auxdisplay/charlcd.h|  1 -
 drivers/auxdisplay/hd44780.c|  2 +-
 drivers/auxdisplay/hd44780_common.c |  1 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 5 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 02392336d7d3..59e0a815bf3d 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -223,9 +223,10 @@ static int charlcd_init_display(struct charlcd *lcd)
 {
void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
u8 init;
 
-   if (lcd->ifwidth != 4 && lcd->ifwidth != 8)
+   if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
return -EINVAL;
 
priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
@@ -238,7 +239,7 @@ static int charlcd_init_display(struct charlcd *lcd)
 * the LCD is in 8-bit mode afterwards
 */
init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
-   if (lcd->ifwidth == 4) {
+   if (hdc->ifwidth == 4) {
init >>= 4;
write_cmd_raw = lcd->ops->write_cmd_raw4;
} else {
@@ -251,7 +252,7 @@ static int charlcd_init_display(struct charlcd *lcd)
write_cmd_raw(lcd, init);
long_sleep(10);
 
-   if (lcd->ifwidth == 4) {
+   if (hdc->ifwidth == 4) {
/* Switch to 4-bit mode, 1 line, small fonts */
lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
long_sleep(10);
@@ -260,7 +261,7 @@ static int charlcd_init_display(struct charlcd *lcd)
/* set font height and lines number */
lcd->ops->write_cmd(lcd,
LCD_CMD_FUNCTION_SET |
-   ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
long_sleep(10);
@@ -543,7 +544,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
lcd->ops->write_cmd(lcd,
LCD_CMD_FUNCTION_SET |
-   ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 
0) |
((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
/* check whether L flag was changed */
@@ -794,7 +795,6 @@ struct charlcd *charlcd_alloc(void)
priv->esc_seq.len = -1;
 
lcd = >lcd;
-   lcd->ifwidth = 8;
 
return lcd;
 }
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 2a12d07705a3..5dce9dd36562 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -18,7 +18,6 @@ struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
 
-   int ifwidth;/* 4-bit or 8-bit (default) */
int height;
int width;
 
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 0603af8f2336..f6786239c36f 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -275,7 +275,7 @@ static int hd44780_probe(struct platform_device *pdev)
/* Optional properties */
device_property_read_u32(dev, "internal-buffer-width", >bwidth);
 
-   lcd->ifwidth = ifwidth;
+   hdc->ifwidth = ifwidth;
lcd->ops = ifwidth == 8 ? _ops_gpio8 : _ops_gpio4;
 
ret = charlcd_register(lcd);
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 3a05fd30cae0..4968461f0c4a 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -12,6 +12,7 @@ struct hd44780_common *hd44780_common_alloc(void)
if (!hd)
return NULL;
 
+   hd->ifwidth = 8;
hd->bwidth = DEFAULT_LCD_BWIDTH;
hd->hwidth = DEFAULT_LCD_HWIDTH;
return hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 9647d24c4490..54cbe5a489d7 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++

[PATCH v6 07/25] auxdisplay: Move addr out of charlcd_priv

2020-11-03 Thread poeschel
From: Lars Poeschel 

Move out the struct addr from struct charlcd_priv into the less private
struct charlcd. This member is used to pass position information. The
individual drivers need to be able to read this information, so we move
this out of charlcd_priv to charlcd structure.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 61 +++-
 drivers/auxdisplay/charlcd.h |  6 
 2 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index ce6622f71c34..1b37d4bc38f9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -72,12 +72,6 @@ struct charlcd_priv {
/* contains the LCD config state */
unsigned long int flags;
 
-   /* Contains the LCD X and Y offset */
-   struct {
-   unsigned long int x;
-   unsigned long int y;
-   } addr;
-
/* Current escape sequence and it's length or -1 if outside */
struct {
char buf[LCD_ESCAPE_LEN + 1];
@@ -148,7 +142,6 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
 
@@ -156,37 +149,34 @@ static void charlcd_gotoxy(struct charlcd *lcd)
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = priv->addr.x < hdc->bwidth ? priv->addr.x & (hdc->hwidth - 1)
+   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
  : hdc->bwidth - 1;
-   if (priv->addr.y & 1)
+   if (lcd->addr.y & 1)
addr += hdc->hwidth;
-   if (priv->addr.y & 2)
+   if (lcd->addr.y & 2)
addr += hdc->bwidth;
hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
-
-   priv->addr.x = 0;
-   priv->addr.y = 0;
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
charlcd_gotoxy(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
 
-   if (priv->addr.x < hdc->bwidth) {
+   if (lcd->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
hdc->write_data(hdc, c);
-   priv->addr.x++;
+   lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (priv->addr.x == hdc->bwidth)
+   if (lcd->addr.x == hdc->bwidth)
charlcd_gotoxy(lcd);
}
 }
@@ -210,12 +200,11 @@ static void charlcd_clear_fast(struct charlcd *lcd)
 /* clears the display and resets X/Y */
 static void charlcd_clear_display(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
 
hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   priv->addr.x = 0;
-   priv->addr.y = 0;
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
/* we must wait a few milliseconds (15) */
long_sleep(15);
 }
@@ -415,21 +404,21 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'l':   /* Shift Cursor Left */
-   if (priv->addr.x > 0) {
+   if (lcd->addr.x > 0) {
/* back one char if not at end of line */
-   if (priv->addr.x < hdc->bwidth)
+   if (lcd->addr.x < hdc->bwidth)
hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   priv->addr.x--;
+   lcd->addr.x--;
}
processed = 1;
break;
case 'r':   /* shift cursor right */
-   if (priv->addr.x < lcd->width) {
+   if (lcd->addr.x < lcd->width) {
/* allow the cursor to pass the end of the line */
-   if (priv->addr.x < (hdc->bwidth - 1))
+   if (lcd->addr.x < (hdc->bwidth - 1))
hdc->write_cmd(hdc,
LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
-   priv->addr.x++;
+   lcd->addr.x++;
}
processed = 1;
break;
@@ -446,7 +43

[PATCH v6 06/25] auxdisplay: Move write_cmd pointers to hd44780 drivers

2020-11-03 Thread poeschel
From: Lars Poeschel 

The write_cmd function is used to send commands to hd44780 displays.
The individual hd44780 drivers then implement their appropriate way of
doing this with their supported displays. So we move this pointer so
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 45 +++--
 drivers/auxdisplay/charlcd.h|  5 
 drivers/auxdisplay/hd44780.c| 15 --
 drivers/auxdisplay/hd44780_common.h |  3 ++
 drivers/auxdisplay/panel.c  | 12 
 5 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index df54078656c1..ce6622f71c34 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -162,7 +162,7 @@ static void charlcd_gotoxy(struct charlcd *lcd)
addr += hdc->hwidth;
if (priv->addr.y & 2)
addr += hdc->bwidth;
-   lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
+   hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
@@ -211,8 +211,9 @@ static void charlcd_clear_fast(struct charlcd *lcd)
 static void charlcd_clear_display(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
-   lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR);
+   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
priv->addr.x = 0;
priv->addr.y = 0;
/* we must wait a few milliseconds (15) */
@@ -221,7 +222,7 @@ static void charlcd_clear_display(struct charlcd *lcd)
 
 static int charlcd_init_display(struct charlcd *lcd)
 {
-   void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
+   void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
u8 init;
@@ -241,25 +242,25 @@ static int charlcd_init_display(struct charlcd *lcd)
init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
if (hdc->ifwidth == 4) {
init >>= 4;
-   write_cmd_raw = lcd->ops->write_cmd_raw4;
+   write_cmd_raw = hdc->write_cmd_raw4;
} else {
-   write_cmd_raw = lcd->ops->write_cmd;
+   write_cmd_raw = hdc->write_cmd;
}
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
 
if (hdc->ifwidth == 4) {
/* Switch to 4-bit mode, 1 line, small fonts */
-   lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
+   hdc->write_cmd_raw4(hdc, LCD_CMD_FUNCTION_SET >> 4);
long_sleep(10);
}
 
/* set font height and lines number */
-   lcd->ops->write_cmd(lcd,
+   hdc->write_cmd(hdc,
LCD_CMD_FUNCTION_SET |
((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
@@ -267,10 +268,10 @@ static int charlcd_init_display(struct charlcd *lcd)
long_sleep(10);
 
/* display off, cursor off, blink off */
-   lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CTRL);
+   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CTRL);
long_sleep(10);
 
-   lcd->ops->write_cmd(lcd,
+   hdc->write_cmd(hdc,
LCD_CMD_DISPLAY_CTRL |  /* set display mode */
((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
@@ -281,7 +282,7 @@ static int charlcd_init_display(struct charlcd *lcd)
long_sleep(10);
 
/* entry mode set : increment, cursor shifting */
-   lcd->ops->write_cmd(lcd, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
+   hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
 
charlcd_clear_display(lcd);
return 0;
@@ -417,7 +418,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (priv->addr.x > 0) {
/* back one char if not at end of line */
if (priv->addr.x < hdc->bwidth)
-   lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
+   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
priv->addr.x--;
}
processed = 1;
@@ -426,18 +427,18 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (priv->addr.x < lcd-

[PATCH v6 13/25] auxdisplay: Make use of enum for backlight on / off

2020-11-03 Thread poeschel
From: Lars Poeschel 

To turn the backlight on or off use our new enum CHARLCD_ON /
CHARLCD_OFF.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 154419513186..9631f70e8128 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -115,7 +115,7 @@ static void charlcd_bl_off(struct work_struct *work)
if (priv->bl_tempo) {
priv->bl_tempo = false;
if (!(priv->flags & LCD_FLAG_L))
-   priv->lcd.ops->backlight(>lcd, 0);
+   priv->lcd.ops->backlight(>lcd, CHARLCD_OFF);
}
mutex_unlock(>bl_tempo_lock);
 }
@@ -132,7 +132,7 @@ void charlcd_poke(struct charlcd *lcd)
 
mutex_lock(>bl_tempo_lock);
if (!priv->bl_tempo && !(priv->flags & LCD_FLAG_L))
-   lcd->ops->backlight(lcd, 1);
+   lcd->ops->backlight(lcd, CHARLCD_ON);
priv->bl_tempo = true;
schedule_delayed_work(>bl_work, LCD_BL_TEMPO_PERIOD * HZ);
mutex_unlock(>bl_tempo_lock);
@@ -829,7 +829,7 @@ int charlcd_unregister(struct charlcd *lcd)
the_charlcd = NULL;
if (lcd->ops->backlight) {
cancel_delayed_work_sync(>bl_work);
-   priv->lcd.ops->backlight(>lcd, 0);
+   priv->lcd.ops->backlight(>lcd, CHARLCD_OFF);
}
 
return 0;
-- 
2.28.0



[PATCH v6 08/25] auxdisplay: hd44780_common_print

2020-11-03 Thread poeschel
From: Lars Poeschel 

We create a hd44780_common_print function. It is derived from the
original charlcd_print. charlcd_print becomes a device independent print
function, that then only calls via its ops function pointers, into the
print function offered by drivers.

Reported-by: kernel test robot 
Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix some typos

Changes in v3:
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
---
 drivers/auxdisplay/charlcd.c| 28 +++-
 drivers/auxdisplay/charlcd.h| 12 
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 14 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 5 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 1b37d4bc38f9..72ed004a8980 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -167,18 +167,15 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
+   if (lcd->char_conv)
+   c = lcd->char_conv[(unsigned char)c];
 
-   if (lcd->addr.x < hdc->bwidth) {
-   if (lcd->char_conv)
-   c = lcd->char_conv[(unsigned char)c];
-   hdc->write_data(hdc, c);
+   if (!lcd->ops->print(lcd, c))
lcd->addr.x++;
 
-   /* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == hdc->bwidth)
-   charlcd_gotoxy(lcd);
-   }
+   /* prevents the cursor from wrapping onto the next line */
+   if (lcd->addr.x == lcd->width)
+   charlcd_gotoxy(lcd);
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
@@ -192,7 +189,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
lcd->ops->clear_fast(lcd);
else
for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
 
charlcd_home(lcd);
 }
@@ -433,12 +430,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'k': { /* kill end of line */
-   int x;
+   int x, xs, ys;
 
+   xs = lcd->addr.x;
+   ys = lcd->addr.y;
for (x = lcd->addr.x; x < hdc->bwidth; x++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
 
/* restore cursor position */
+   lcd->addr.x = xs;
+   lcd->addr.y = ys;
charlcd_gotoxy(lcd);
processed = 1;
break;
@@ -591,7 +592,8 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * go to the beginning of the next line
 */
for (; lcd->addr.x < hdc->bwidth; lcd->addr.x++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
+
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
charlcd_gotoxy(lcd);
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index ff4896af2189..94922e3c1c4c 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -30,9 +30,21 @@ struct charlcd {
void *drvdata;
 };
 
+/**
+ * struct charlcd_ops - Functions used by charlcd. Drivers have to implement
+ * these.
+ * @clear_fast: Clear the whole display and set cursor to position 0, 0.
+ * Optional.
+ * @backlight: Turn backlight on or off. Optional.
+ * @print: Print one character to the display at current cursor position.
+ * The cursor is advanced by charlcd.
+ * The buffered cursor position is advanced by charlcd. The cursor should not
+ * wrap to the next line at the end of a line.
+ */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
+   int (*print)(struct charlcd *lcd, int c);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index dc4738563298..9680bb611639 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -126,6 +126,7 @@ static void hd44780_write_data_gpio8(struct hd44780_common 
*hdc, int data)
 
 static const struct charlcd_ops hd44780_ops_gpio8 = {
.backlight  = hd44780_backlight,
+   .print  = hd44780_common_print,
 };
 
 /* Send a command to the LCD panel in 4 

[PATCH v6 10/25] auxdisplay: add home to charlcd_ops

2020-11-03 Thread poeschel
From: Lars Poeschel 

This adds a home function to the charlcd_ops struct and offer an
implementation for hd44780_common. This implementation is used by our
two hd44780 drivers. This is to make charlcd device independent.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 2 +-
 drivers/auxdisplay/charlcd.h| 3 +++
 drivers/auxdisplay/hd44780.c| 2 ++
 drivers/auxdisplay/hd44780_common.c | 8 
 drivers/auxdisplay/hd44780_common.h | 1 +
 drivers/auxdisplay/panel.c  | 3 +++
 6 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index d6f971eea6ae..44dd6e02eaf9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -144,7 +144,7 @@ static void charlcd_home(struct charlcd *lcd)
 {
lcd->addr.x = 0;
lcd->addr.y = 0;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->home(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index f36cc80ce385..236fd0e9e8ab 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -41,12 +41,15 @@ struct charlcd {
  * wrap to the next line at the end of a line.
  * @gotoxy: Set cursor to x, y. The x and y values to set the cursor to are
  * previously set in addr.x and addr.y by charlcd.
+ * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
+ * charlcd prior to calling this function.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
+   int (*home)(struct charlcd *lcd);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 4d9478f6e5ff..b0893ea49165 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -128,6 +128,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.backlight  = hd44780_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -173,6 +174,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.backlight  = hd44780_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index f86eb2f27cee..ea62beada9d8 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -41,6 +41,14 @@ int hd44780_common_gotoxy(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_gotoxy);
 
+int hd44780_common_home(struct charlcd *lcd)
+{
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
+   return hd44780_common_gotoxy(lcd);
+}
+EXPORT_SYMBOL_GPL(hd44780_common_home);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index d8cbea4a8658..c91070ed931b 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -16,4 +16,5 @@ struct hd44780_common {
 
 int hd44780_common_print(struct charlcd *lcd, int c);
 int hd44780_common_gotoxy(struct charlcd *lcd);
+int hd44780_common_home(struct charlcd *lcd);
 struct hd44780_common *hd44780_common_alloc(void);
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 75894eacd12f..b1e874f07456 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -876,18 +876,21 @@ static const struct charlcd_ops charlcd_serial_ops = {
.clear_fast = lcd_clear_fast_s,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
.clear_fast = lcd_clear_fast_p8,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
.clear_fast = lcd_clear_fast_tilcd,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0



[PATCH v6 00/25] Make charlcd device independent

2020-11-03 Thread poeschel
From: Lars Poeschel 

This tries to make charlcd device independent. At the moment hd44780
device specific code is contained deep in charlcd. This moves this out
into a hd44780_common module, where the two hd44780 drivers we have at
the moment (hd44780 and panel) can use this from. The goal is that at
the end other drivers can use the charlcd interface.
I add one such driver for a modtronix lcd displau  with the last patch.
I submitted this already some time ago, where the wish was so split
this into smaller chunks what I try to do with this patchset.

This is v6 of the patchset. I address a two review comments from Miguel.
I fixed the Kconfig menu of auxdisplay. It does now present a submenu
again. And I fixed some typos in the commit message of patch 23.

As a note to patch 23:
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used so set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistens across different displays.
The new behaviour is to stop writing character at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependent anymore.

Link: https://lore.kernel.org/lkml/20191016082430.5955-1-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/CANiq72kS-u_Xd_m+2CQVh-JCncPf1XNXrXAZ=4z+mze8fwv...@mail.gmail.com/

Changes in v6:
- patch 2: Fix Kconfig so that auxdisplay is now a submenu again
- patch 23: Fix some typos in commit message

Changes in v5:
- patch 1: Fix a commit message typo: of -> on
- patch 2: Remove some unnecessary newlines
- patch 8: Fix some typos
- patch 14: Fix commit message typo: it's -> its
- patch 15: this patch is squashed together from the former individual
  hd44780_common_ function patches
- patch 16: combined two cleanup patches
- patch 17: I did previously undo commit 3f03b6498 which was a mistake.
  This is now corrected.
- patch 24: Picked up Robs Reviewed-by
- patch 25: use hex_to_bin like in commit 3f03b6498 but for the lcd2s.c
  file

Changes in v4:
- modtronix -> Modtronix in new lcd2s driver
- Kconfig: remove "default n" in new lcd2s driver

Changes in v3:
- Fix some typos in Kconfig stuff
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
- new patch to reduce display timeout
- better patch description to why not move cursor beyond end of a line
- Fixed make dt_binding_doc errors

Changes in v2:
- split whole patch into many smaller chunks
- device tree doc in yaml

Lars Poeschel (25):
  auxdisplay: Use an enum for charlcd  backlight on/off ops
  auxdisplay: Introduce hd44780_common.[ch]
  auxdisplay: Move hwidth and bwidth to struct hd44780_common
  auxdisplay: Move ifwidth to struct hd44780_common
  auxdisplay: Move write_data pointer to hd44780_common
  auxdisplay: Move write_cmd pointers to hd44780 drivers
  auxdisplay: Move addr out of charlcd_priv
  auxdisplay: hd44780_common_print
  auxdisplay: provide hd44780_common_gotoxy
  auxdisplay: add home to charlcd_ops
  auxdisplay: Move clear_display to hd44780_common
  auxdisplay: make charlcd_backlight visible to hd44780_common
  auxdisplay: Make use of enum for backlight on / off
  auxdisplay: Move init_display to hd44780_common
  auxdisplay: implement various hd44780_common_ functions
  auxdisplay: cleanup unnecessary hd44780 code in charlcd
  auxdisplay: Move char redefine code to hd44780_common
  auxdisplay: Call charlcd_backlight in place
  auxdisplay: hd44780_common: Reduce clear_display timeout
  auxdisplay: hd44780: Remove clear_fast
  auxdisplay: charlcd: replace last device specific stuff
  auxdisplay: Change gotoxy calling interface
  auxdisplay: charlcd: Do not print chars at end of line
  auxdisplay: lcd2s DT binding doc
  auxdisplay: add a driver for lcd2s character display

 .../bindings/auxdisplay/modtronix,lcd2s.yaml  |  58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 drivers/auxdisplay/Kconfig|  30 ++
 drivers/auxdisplay/Makefile   |   2 +
 drivers/auxdisplay/charlcd.c  | 412 +-
 drivers/auxdisplay/charlcd.h  |  86 +++-
 drivers/auxdisplay/hd44780.c  | 120 +++--
 drivers/auxdisplay/hd44780_common.c   | 361 +++
 drivers/auxdisplay/hd44780_common.h   |  33 ++
 drivers/auxdisplay/lcd2s.c| 403 +
 drivers/auxdisplay/panel.c| 180 
 11 files changed, 1237 insertions(+), 450 deletions(-)
 crea

[PATCH v6 02/25] auxdisplay: Introduce hd44780_common.[ch]

2020-11-03 Thread poeschel
From: Lars Poeschel 

There is some hd44780 specific code in charlcd and this code is used by
multiple drivers. To make charlcd independent from this device specific
code this has to be moved to a place where the multiple drivers can
share their common code. This common place is now introduced as
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v6:
- Fix Kconfig so that auxdisplay is now a submenu again

Changes in v5:
- Remove some unnecessary newlines

Changes in v3:
- Fix some typos
---
 drivers/auxdisplay/Kconfig  | 20 ++
 drivers/auxdisplay/Makefile |  1 +
 drivers/auxdisplay/hd44780.c| 43 +++--
 drivers/auxdisplay/hd44780_common.c | 19 +
 drivers/auxdisplay/hd44780_common.h |  7 +
 drivers/auxdisplay/panel.c  | 18 ++--
 6 files changed, 91 insertions(+), 17 deletions(-)
 create mode 100644 drivers/auxdisplay/hd44780_common.c
 create mode 100644 drivers/auxdisplay/hd44780_common.h

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 81757eeded68..aaf2d66357a1 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -16,10 +16,29 @@ menuconfig AUXDISPLAY
 
 if AUXDISPLAY
 
+config CHARLCD
+   tristate "Character LCD core support" if COMPILE_TEST
+   help
+ This is the base system for character-based LCD displays.
+ It makes no sense to have this alone, you select your display driver
+ and if it needs the charlcd core, it will select it automatically.
+ This is some character LCD core interface that multiple drivers can
+ use.
+
+config HD44780_COMMON
+   tristate "Common functions for HD44780 (and compatibles) LCD displays" 
if COMPILE_TEST
+   help
+ This is a module with the common symbols for HD44780 (and compatibles)
+ displays. This is the code that multiple other modules use. It is not
+ useful alone. If you have some sort of HD44780 compatible display,
+ you very likely use this. It is selected automatically by selecting
+ your concrete display.
+
 config HD44780
tristate "HD44780 Character LCD support"
depends on GPIOLIB || COMPILE_TEST
select CHARLCD
+   select HD44780_COMMON
help
  Enable support for Character LCDs using a HD44780 controller.
  The LCD is accessible through the /dev/lcd char device (10, 156).
@@ -168,6 +187,7 @@ menuconfig PARPORT_PANEL
tristate "Parallel port LCD/Keypad Panel support"
depends on PARPORT
select CHARLCD
+   select HD44780_COMMON
help
  Say Y here if you have an HD44780 or KS-0074 LCD connected to your
  parallel port. This driver also features 4 and 6-key keypads. The LCD
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index cf54b5efb07e..7e8a8c3eb3c3 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_CHARLCD)  += charlcd.o
+obj-$(CONFIG_HD44780_COMMON)   += hd44780_common.o
 obj-$(CONFIG_ARM_CHARLCD)  += arm-charlcd.o
 obj-$(CONFIG_KS0108)   += ks0108.o
 obj-$(CONFIG_CFAG12864B)   += cfag12864b.o cfag12864bfb.o
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 5982158557bb..271dba9cd108 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -15,6 +15,7 @@
 #include 
 
 #include "charlcd.h"
+#include "hd44780_common.h"
 
 enum hd44780_pin {
/* Order does matter due to writing to GPIO array subsets! */
@@ -179,8 +180,9 @@ static int hd44780_probe(struct platform_device *pdev)
struct device *dev = >dev;
unsigned int i, base;
struct charlcd *lcd;
+   struct hd44780_common *hdc;
struct hd44780 *hd;
-   int ifwidth, ret;
+   int ifwidth, ret = -ENOMEM;
 
/* Required pins */
ifwidth = gpiod_count(dev, "data");
@@ -198,31 +200,39 @@ static int hd44780_probe(struct platform_device *pdev)
return -EINVAL;
}
 
+   hdc = hd44780_common_alloc();
+   if (!hdc)
+   return -ENOMEM;
+
lcd = charlcd_alloc(sizeof(struct hd44780));
if (!lcd)
-   return -ENOMEM;
+   goto fail1;
 
-   hd = lcd->drvdata;
+   hd = kzalloc(sizeof(struct hd44780), GFP_KERNEL);
+   if (!hd)
+   goto fail2;
 
+   hdc->hd44780 = hd;
+   lcd->drvdata = hdc;
for (i = 0; i < ifwidth; i++) {
hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i,
  GPIOD_OUT_LOW);
if (IS_ERR(hd->pins[base + i])) {
ret = PTR_ERR(hd->pins[base + i]);
-   goto fail;
+  

[PATCH v6 23/25] auxdisplay: charlcd: Do not print chars at end of line

2020-11-03 Thread poeschel
From: Lars Poeschel 

Skip printing characters at the end of a display line. This fits to the
behaviour we already had, that the cursor is nailed to the last position
of a line.
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used to set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistent across different displays.
The new behaviour is to stop writing characters at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependent anymore.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v6:
- Fix some typos in commit message

Changes in v3:
- Better patch description
---
 drivers/auxdisplay/charlcd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index ef10b5ca0e16..f43430e9dcee 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -111,6 +111,9 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
+   if (lcd->addr.x >= lcd->width)
+   return;
+
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
-- 
2.28.0



[PATCH v6 18/25] auxdisplay: Call charlcd_backlight in place

2020-11-03 Thread poeschel
From: Lars Poeschel 

This moves the call to charlcd_backlight from the end of the switch
into the actual case statement that originates the change of the
backlight. This is more consistent to what is now found in this switch.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index dca1b138a239..0f0568a4bd35 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -259,10 +259,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case '+':   /* Back light ON */
priv->flags |= LCD_FLAG_L;
+   if (priv->flags != oldflags)
+   charlcd_backlight(lcd, CHARLCD_ON);
+
processed = 1;
break;
case '-':   /* Back light OFF */
priv->flags &= ~LCD_FLAG_L;
+   if (priv->flags != oldflags)
+   charlcd_backlight(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case '*':   /* Flash back light */
@@ -363,14 +369,6 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
}
 
-   /* TODO: This indent party here got ugly, clean it! */
-   /* Check whether one flag was changed */
-   if (oldflags == priv->flags)
-   return processed;
-
-   if ((oldflags ^ priv->flags) & LCD_FLAG_L)
-   charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
-
return processed;
 }
 
-- 
2.28.0



[PATCH v6 16/25] auxdisplay: cleanup unnecessary hd44780 code in charlcd

2020-11-03 Thread poeschel
From: Lars Poeschel 

This cleans up now unnecessary hd44780 specific code from charlcd. We
obsoleted this with the last patch. So another chunk of hd44780 specific
code can be dropped from charlcd.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- combined two cleanup patches
---
 drivers/auxdisplay/charlcd.c | 32 +---
 1 file changed, 1 insertion(+), 31 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 281a3259c144..29737c3e18f6 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -25,21 +25,8 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-/* LCD commands */
-#define LCD_CMD_DISPLAY_CTRL   0x08/* Display control */
-#define LCD_CMD_DISPLAY_ON 0x04/* Set display on */
-#define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
-#define LCD_CMD_BLINK_ON   0x01/* Set blink on */
-
-#define LCD_CMD_FUNCTION_SET   0x20/* Set function */
-#define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
-#define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
-#define LCD_CMD_FONT_5X10_DOTS 0x04/* Set char font to 5x10 dots */
-
 #define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
 
-#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
-
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
 
@@ -431,24 +418,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (oldflags == priv->flags)
return processed;
 
-   /* check whether one of B,C,D flags were changed */
-   if ((oldflags ^ priv->flags) &
-   (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
-   /* set display mode */
-   hdc->write_cmd(hdc,
-   LCD_CMD_DISPLAY_CTRL |
-   ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
-   ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
-   ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
-   /* check whether one of F,N flags was changed */
-   else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
-   hdc->write_cmd(hdc,
-   LCD_CMD_FUNCTION_SET |
-   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-   ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 
0) |
-   ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
-   /* check whether L flag was changed */
-   else if ((oldflags ^ priv->flags) & LCD_FLAG_L)
+   if ((oldflags ^ priv->flags) & LCD_FLAG_L)
charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
 
return processed;
-- 
2.28.0



[PATCH v6 05/25] auxdisplay: Move write_data pointer to hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

This moves the write_data function pointer from struct charlcd_ops to
struct hd44780_common. This is the function that actually writes the
character to the display. This hd44780 hardware specific function is
used by two drivers at the moment.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 12 ++--
 drivers/auxdisplay/charlcd.h|  1 -
 drivers/auxdisplay/hd44780.c| 16 +---
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  | 12 ++--
 5 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 59e0a815bf3d..df54078656c1 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -182,7 +182,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
if (priv->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
-   lcd->ops->write_data(lcd, c);
+   hdc->write_data(hdc, c);
priv->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
@@ -202,7 +202,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
lcd->ops->clear_fast(lcd);
else
for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
 
charlcd_home(lcd);
 }
@@ -446,7 +446,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
int x;
 
for (x = priv->addr.x; x < hdc->bwidth; x++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
 
/* restore cursor position */
charlcd_gotoxy(lcd);
@@ -505,7 +505,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
for (addr = 0; addr < cgoffset; addr++)
-   lcd->ops->write_data(lcd, cgbytes[addr]);
+   hdc->write_data(hdc, cgbytes[addr]);
 
/* ensures that we stop writing to CGRAM */
charlcd_gotoxy(lcd);
@@ -587,7 +587,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
priv->addr.x--;
}
/* replace with a space */
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
/* back one char again */
lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
break;
@@ -601,7 +601,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * go to the beginning of the next line
 */
for (; priv->addr.x < hdc->bwidth; priv->addr.x++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
priv->addr.x = 0;
priv->addr.y = (priv->addr.y + 1) % lcd->height;
charlcd_gotoxy(lcd);
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5dce9dd36562..fba4f2cd42c4 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -27,7 +27,6 @@ struct charlcd {
 struct charlcd_ops {
/* Required */
void (*write_cmd)(struct charlcd *lcd, int cmd);
-   void (*write_data)(struct charlcd *lcd, int data);
 
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index f6786239c36f..922f0e0d2e6d 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -115,9 +115,8 @@ static void hd44780_write_cmd_gpio8(struct charlcd *lcd, 
int cmd)
 }
 
 /* Send data to the LCD panel in 8 bit GPIO mode */
-static void hd44780_write_data_gpio8(struct charlcd *lcd, int data)
+static void hd44780_write_data_gpio8(struct hd44780_common *hdc, int data)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
struct hd44780 *hd = hdc->hd44780;
 
hd44780_write_gpio8(hd, data, 1);
@@ -128,7 +127,6 @@ static void hd44780_write_data_gpio8(struct charlcd *lcd, 
int data)
 
 static const struct charlcd_ops hd44780_ops_gpio8 = {
.write_cmd  = hd44780_write_cmd_gpio8,
-   .write_data = hd44780_write_data_gpio8,
.backlight  = hd44780_backlight,
 };
 
@@ -163,9 +161,8 @@ static void hd44780_write_cmd_raw_gpio4(struct charl

[PATCH v6 14/25] auxdisplay: Move init_display to hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

The init_display function is moved over to hd44780_common. charlcd uses
it via its ops function pointer and drivers initialize the ops with the
common hd44780_common_init_display function.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix commit message typo: it's -> its
---
 drivers/auxdisplay/charlcd.c| 95 ++---
 drivers/auxdisplay/charlcd.h|  9 +++
 drivers/auxdisplay/hd44780.c|  2 +
 drivers/auxdisplay/hd44780_common.c | 88 ++
 drivers/auxdisplay/hd44780_common.h |  2 +
 drivers/auxdisplay/panel.c  |  3 +
 6 files changed, 110 insertions(+), 89 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 9631f70e8128..94f6b0afab13 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -8,7 +8,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -26,17 +25,7 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-#define LCD_FLAG_B 0x0004  /* Blink on */
-#define LCD_FLAG_C 0x0008  /* Cursor on */
-#define LCD_FLAG_D 0x0010  /* Display on */
-#define LCD_FLAG_F 0x0020  /* Large font mode */
-#define LCD_FLAG_N 0x0040  /* 2-rows mode */
-#define LCD_FLAG_L 0x0080  /* Backlight enabled */
-
 /* LCD commands */
-#define LCD_CMD_ENTRY_MODE 0x04/* Set entry mode */
-#define LCD_CMD_CURSOR_INC 0x02/* Increment cursor */
-
 #define LCD_CMD_DISPLAY_CTRL   0x08/* Display control */
 #define LCD_CMD_DISPLAY_ON 0x04/* Set display on */
 #define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
@@ -84,12 +73,6 @@ struct charlcd_priv {
 /* Device single-open policy control */
 static atomic_t charlcd_available = ATOMIC_INIT(1);
 
-/* sleeps that many milliseconds with a reschedule */
-static void long_sleep(int ms)
-{
-   schedule_timeout_interruptible(msecs_to_jiffies(ms));
-}
-
 /* turn the backlight on or off */
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
@@ -177,76 +160,6 @@ static void charlcd_clear_fast(struct charlcd *lcd)
charlcd_home(lcd);
 }
 
-static int charlcd_init_display(struct charlcd *lcd)
-{
-   void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
-   u8 init;
-
-   if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
-   return -EINVAL;
-
-   priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
- LCD_FLAG_C | LCD_FLAG_B;
-
-   long_sleep(20); /* wait 20 ms after power-up for the paranoid */
-
-   /*
-* 8-bit mode, 1 line, small fonts; let's do it 3 times, to make sure
-* the LCD is in 8-bit mode afterwards
-*/
-   init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
-   if (hdc->ifwidth == 4) {
-   init >>= 4;
-   write_cmd_raw = hdc->write_cmd_raw4;
-   } else {
-   write_cmd_raw = hdc->write_cmd;
-   }
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-
-   if (hdc->ifwidth == 4) {
-   /* Switch to 4-bit mode, 1 line, small fonts */
-   hdc->write_cmd_raw4(hdc, LCD_CMD_FUNCTION_SET >> 4);
-   long_sleep(10);
-   }
-
-   /* set font height and lines number */
-   hdc->write_cmd(hdc,
-   LCD_CMD_FUNCTION_SET |
-   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-   ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
-   ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
-   long_sleep(10);
-
-   /* display off, cursor off, blink off */
-   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CTRL);
-   long_sleep(10);
-
-   hdc->write_cmd(hdc,
-   LCD_CMD_DISPLAY_CTRL |  /* set display mode */
-   ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
-   ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
-   ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
-
-   charlcd_backlight(lcd, (priv->flags & LCD_FLAG_L) ? 1 : 0);
-
-   long_sleep(10);
-
-   /* entry mode set : increment, cursor shifting */
-   hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
-
-   lcd->ops->clear_display(lcd);
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   return 0;
-}
-
 /*
  * Parses a movement command of the form "(.*);", where the group can be
  * any number of subcommands of the form "(x|

[PATCH v6 20/25] auxdisplay: hd44780: Remove clear_fast

2020-11-03 Thread poeschel
From: Lars Poeschel 

We remove the hd44780_clear_fast (display) clear implementation. With
the new timeout the normal clear_display is reasonably fast. So there is
no need for a clear_fast anymore.

Link: https://lore.kernel.org/lkml/20200922092121.gg16...@1wt.eu/

Signed-off-by: Lars Poeschel 
---
Changes in v3:
- This patch is squashed together from 26, 27 and 28 from previous patch
  set:
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-27-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-28-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-29-poesc...@lemonage.de/

- Additionally this now removes clear_fast from charlcd_ops and from
  panel driver.
---
 drivers/auxdisplay/charlcd.c | 21 ---
 drivers/auxdisplay/charlcd.h |  7 ++--
 drivers/auxdisplay/panel.c   | 67 
 3 files changed, 8 insertions(+), 87 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 0f0568a4bd35..077c01e87127 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -125,20 +125,11 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->ops->gotoxy(lcd);
 }
 
-static void charlcd_clear_fast(struct charlcd *lcd)
+static void charlcd_clear_display(struct charlcd *lcd)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
-   int pos;
-
-   charlcd_home(lcd);
-
-   if (lcd->ops->clear_fast)
-   lcd->ops->clear_fast(lcd);
-   else
-   for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   lcd->ops->print(lcd, ' ');
-
-   charlcd_home(lcd);
+   lcd->ops->clear_display(lcd);
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
 }
 
 /*
@@ -409,7 +400,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
break;
case '\f':
/* quickly clear the display */
-   charlcd_clear_fast(lcd);
+   charlcd_clear_display(lcd);
break;
case '\n':
/*
@@ -448,7 +439,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 
if (!strcmp(priv->esc_seq.buf, "[2J")) {
/* clear the display */
-   charlcd_clear_fast(lcd);
+   charlcd_clear_display(lcd);
processed = 1;
} else if (!strcmp(priv->esc_seq.buf, "[H")) {
/* cursor to home */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 3339e8c2554e..e7e9b12b1e99 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -55,8 +55,6 @@ struct charlcd {
 /**
  * struct charlcd_ops - Functions used by charlcd. Drivers have to implement
  * these.
- * @clear_fast: Clear the whole display and set cursor to position 0, 0.
- * Optional.
  * @backlight: Turn backlight on or off. Optional.
  * @print: Print one character to the display at current cursor position.
  * The buffered cursor position is advanced by charlcd. The cursor should not
@@ -65,8 +63,8 @@ struct charlcd {
  * previously set in addr.x and addr.y by charlcd.
  * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
  * charlcd prior to calling this function.
- * @clear_display: Again clear the whole display, set the cursor to 0, 0. The
- * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
+ * @clear_display: Clear the whole display and set the cursor to 0, 0. The
+ * values in addr.x and addr.y are set to 0, 0 by charlcd after to calling this
  * function.
  * @init_display: Initialize the display.
  * @shift_cursor: Shift cursor left or right one position.
@@ -78,7 +76,6 @@ struct charlcd {
  * @redefine_char: Redefine the actual pixel matrix of character.
  */
 struct charlcd_ops {
-   void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index b0d2ae5b9be8..e07fadac281d 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -808,72 +808,7 @@ static void lcd_write_data_tilcd(struct hd44780_common 
*hdc, int data)
spin_unlock_irq(_lock);
 }
 
-/* fills the display with spaces and resets X/Y */
-static void lcd_clear_fast_s(struct charlcd *charlcd)
-{
-   struct hd44780_common *hdc = charlcd->drvdata;
-   int pos;
-
-   spin_lock_irq(_lock);
-   for (pos = 0; pos < charlcd->height * hdc->hwidth; pos++) {
-   lcd_send_serial(0x5F);  /* R/W=W, RS=1 */
-   lcd_send_serial(' ' & 

[PATCH v6 12/25] auxdisplay: make charlcd_backlight visible to hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

hd44780_common wants to use the charlcd_backlight function, so make it
visible.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 3 ++-
 drivers/auxdisplay/charlcd.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index fc0daf4987d5..154419513186 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -91,7 +91,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
+void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
@@ -103,6 +103,7 @@ static void charlcd_backlight(struct charlcd *lcd, enum 
charlcd_onoff on)
lcd->ops->backlight(lcd, on);
mutex_unlock(>bl_tempo_lock);
 }
+EXPORT_SYMBOL_GPL(charlcd_backlight);
 
 static void charlcd_bl_off(struct work_struct *work)
 {
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index a6c32c4d1aac..a3210305cae7 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -56,6 +56,7 @@ struct charlcd_ops {
int (*clear_display)(struct charlcd *lcd);
 };
 
+void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
 struct charlcd *charlcd_alloc(void);
 void charlcd_free(struct charlcd *lcd);
 
-- 
2.28.0



[PATCH v6 17/25] auxdisplay: Move char redefine code to hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

Take the code to redefine characters out of charlcd and move it to
hd44780_common, as this is hd44780 specific.
There is now a function hd44780_common_redefine_char that drivers use
and charlcd calls it through its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- I did previously undo commit 3f03b6498 which was a mistake. This is
  now corrected.
---
 drivers/auxdisplay/charlcd.c| 60 +++--
 drivers/auxdisplay/charlcd.h|  2 +
 drivers/auxdisplay/hd44780.c|  2 +
 drivers/auxdisplay/hd44780_common.c | 57 +++
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 ++
 6 files changed, 70 insertions(+), 55 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 29737c3e18f6..dca1b138a239 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -25,8 +25,6 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-#define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
-
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
 
@@ -344,61 +342,13 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
LCD_FLAG_C | LCD_FLAG_B;
processed = 1;
break;
-   case 'G': {
-   /* Generator : LGcx...xx; must have  between '0'
-* and '7', representing the numerical ASCII code of the
-* redefined character, and  a sequence of 16
-* hex digits representing 8 bytes for each character.
-* Most LCDs will only use 5 lower bits of the 7 first
-* bytes.
-*/
-
-   unsigned char cgbytes[8];
-   unsigned char cgaddr;
-   int cgoffset;
-   int shift;
-   char value;
-   int addr;
-
-   if (!strchr(esc, ';'))
-   break;
-
-   esc++;
-
-   cgaddr = *(esc++) - '0';
-   if (cgaddr > 7) {
+   case 'G':
+   if (lcd->ops->redefine_char)
+   processed = lcd->ops->redefine_char(lcd, esc);
+   else
processed = 1;
-   break;
-   }
-
-   cgoffset = 0;
-   shift = 0;
-   value = 0;
-   while (*esc && cgoffset < 8) {
-   int half;
-
-   shift ^= 4;
-
-   half = hex_to_bin(*esc++);
-   if (half < 0)
-   continue;
-
-   value |= half << shift;
-   if (shift == 0) {
-   cgbytes[cgoffset++] = value;
-   value = 0;
-   }
-   }
-
-   hdc->write_cmd(hdc, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
-   for (addr = 0; addr < cgoffset; addr++)
-   hdc->write_data(hdc, cgbytes[addr]);
-
-   /* ensures that we stop writing to CGRAM */
-   lcd->ops->gotoxy(lcd);
-   processed = 1;
break;
-   }
+
case 'x':   /* gotoxy : LxXXX[yYYY]; */
case 'y':   /* gotoxy : LyYYY[xXXX]; */
if (priv->esc_seq.buf[priv->esc_seq.len - 1] != ';')
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5a89bdeb659a..3339e8c2554e 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -75,6 +75,7 @@ struct charlcd {
  * @cursor: Turn cursor on or off.
  * @blink: Turn cursor blink on or off.
  * @lines: One or two lines.
+ * @redefine_char: Redefine the actual pixel matrix of character.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -91,6 +92,7 @@ struct charlcd_ops {
int (*blink)(struct charlcd *lcd, enum charlcd_onoff on);
int (*fontsize)(struct charlcd *lcd, enum charlcd_fontsize size);
int (*lines)(struct charlcd *lcd, enum charlcd_lines lines);
+   int (*redefine_char)(struct charlcd *lcd, char *esc);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 7b7b28d72198..2e5e7c993933 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -138,6 +138,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.blink  = hd44780_common_blink,
.fontsize   = hd44780_common_fontsize,
.lines  = hd44780_common_lines,
+   .redef

[PATCH v6 24/25] auxdisplay: lcd2s DT binding doc

2020-11-03 Thread poeschel
From: Lars Poeschel 

Add a binding doc for the modtronix lcd2s auxdisplay driver. It also
adds modtronix to the list of known vendor-prefixes.

Reviewed-by: Willy Tarreau 
Reviewed-by: Rob Herring 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Picked up Robs Reviewed-by
Changes in v3:
- Fixed make dt_binding_doc errors
Changes in v2:
- Adopted yaml based file format
---
 .../bindings/auxdisplay/modtronix,lcd2s.yaml  | 58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
 2 files changed, 60 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml

diff --git a/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml 
b/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
new file mode 100644
index ..a1d55a2634a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/auxdisplay/modtronix,lcd2s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Modtronix engineering LCD2S Character LCD Display
+
+maintainers:
+  - Lars Poeschel 
+
+description:
+  The LCD2S is a Character LCD Display manufactured by Modtronix Engineering.
+  The display supports a serial I2C and SPI interface. The driver currently
+  only supports the I2C interface.
+
+properties:
+  compatible:
+const: modtronix,lcd2s
+
+  reg:
+maxItems: 1
+description:
+  I2C bus address of the display.
+
+  display-height-chars:
+description: Height of the display, in character cells.
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 1
+maximum: 4
+
+  display-width-chars:
+description: Width of the display, in character cells.
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 16
+maximum: 20
+
+required:
+  - compatible
+  - reg
+  - display-height-chars
+  - display-width-chars
+
+additionalProperties: false
+
+examples:
+  - |
+i2c {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  lcd2s: auxdisplay@28 {
+compatible = "modtronix,lcd2s";
+reg = <0x28>;
+display-height-chars = <4>;
+display-width-chars = <20>;
+  };
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml 
b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 2735be1a8470..65f40ab5a87f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -681,6 +681,8 @@ patternProperties:
 description: MiraMEMS Sensing Technology Co., Ltd.
   "^mitsubishi,.*":
 description: Mitsubishi Electric Corporation
+  "^modtronix,.*":
+description: Modtronix Engineering
   "^mosaixtech,.*":
 description: Mosaix Technologies, Inc.
   "^motorola,.*":
-- 
2.28.0



[PATCH v6 22/25] auxdisplay: Change gotoxy calling interface

2020-11-03 Thread poeschel
From: Lars Poeschel 

Change the calling interface for gotoxy from supplying the x and y
coordinates in the charlcd struct to explicitly supplying x and y in
the function arguments. This is more intuitive and allows for moving
the cursor to positions independent from the position saved in the
charlcd struct.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 10 +-
 drivers/auxdisplay/charlcd.h|  2 +-
 drivers/auxdisplay/hd44780_common.c | 15 ++-
 drivers/auxdisplay/hd44780_common.h |  2 +-
 4 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 59f21401d6a9..ef10b5ca0e16 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -119,7 +119,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
 
/* prevents the cursor from wrapping onto the next line */
if (lcd->addr.x == lcd->width)
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x - 1, lcd->addr.y);
 }
 
 static void charlcd_clear_display(struct charlcd *lcd)
@@ -325,7 +325,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
/* restore cursor position */
lcd->addr.x = xs;
lcd->addr.y = ys;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
processed = 1;
break;
}
@@ -349,7 +349,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
/* If the command is valid, move to the new address */
if (parse_xy(esc, >addr.x, >addr.y))
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
 
/* Regardless of its validity, mark as processed */
processed = 1;
@@ -407,12 +407,12 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
 
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
break;
case '\r':
/* go to the beginning of the same line */
lcd->addr.x = 0;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
break;
case '\t':
/* print a space instead of the tab */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index e7e9b12b1e99..eed80063a6d2 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -78,7 +78,7 @@ struct charlcd {
 struct charlcd_ops {
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
-   int (*gotoxy)(struct charlcd *lcd);
+   int (*gotoxy)(struct charlcd *lcd, unsigned int x, unsigned int y);
int (*home)(struct charlcd *lcd);
int (*clear_display)(struct charlcd *lcd);
int (*init_display)(struct charlcd *lcd);
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index bd93a4d3367e..3934c2eebf33 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -49,7 +49,7 @@ int hd44780_common_print(struct charlcd *lcd, int c)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_print);
 
-int hd44780_common_gotoxy(struct charlcd *lcd)
+int hd44780_common_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y)
 {
struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
@@ -58,11 +58,10 @@ int hd44780_common_gotoxy(struct charlcd *lcd)
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
- : hdc->bwidth - 1;
-   if (lcd->addr.y & 1)
+   addr = x < hdc->bwidth ? x & (hdc->hwidth - 1) : hdc->bwidth - 1;
+   if (y & 1)
addr += hdc->hwidth;
-   if (lcd->addr.y & 2)
+   if (y & 2)
addr += hdc->bwidth;
hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
return 0;
@@ -71,9 +70,7 @@ EXPORT_SYMBOL_GPL(hd44780_common_gotoxy);
 
 int hd44780_common_home(struct charlcd *lcd)
 {
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   return hd44780_common_gotoxy(lcd);
+   return hd44780_common_gotoxy(lcd, 0, 0);
 }
 EXPORT_SYMBOL_GPL(hd44780_common_home);
 
@@ -341,7 +338,7

[PATCH v6 19/25] auxdisplay: hd44780_common: Reduce clear_display timeout

2020-11-03 Thread poeschel
From: Lars Poeschel 

Digging in the hd44780 datasheet revealed that the timeout needed after
clearing the whole display is only 1,64ms not 15ms. So we can reduce
that timeout.

Link: https://lore.kernel.org/lkml/20200922092121.gg16...@1wt.eu/
Link: https://www.crystalfontz.com/controllers/Hitachi/HD44780/433/

Signed-off-by: Lars Poeschel 
---
Changes in v3:
- This patch is new in v3
---
 drivers/auxdisplay/hd44780_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index c528fb8e8808..bd93a4d3367e 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -83,8 +83,8 @@ int hd44780_common_clear_display(struct charlcd *lcd)
struct hd44780_common *hdc = lcd->drvdata;
 
hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   /* we must wait a few milliseconds (15) */
-   long_sleep(15);
+   /* datasheet says to wait 1,64 milliseconds */
+   long_sleep(2);
return 0;
 }
 EXPORT_SYMBOL_GPL(hd44780_common_clear_display);
-- 
2.28.0



[PATCH v6 15/25] auxdisplay: implement various hd44780_common_ functions

2020-11-03 Thread poeschel
From: Lars Poeschel 

This implements various hd44780_common_ functions for hd44780 compatible
display drivers to use. charlcd then calls these functions through its
ops function pointer.
The functions namely are:
- hd44780_common_shift_cursor
- hd44780_common_display_shift
- hd44780_common_display
- hd44780_common_cursor
- hd44780_common_blink
- hd44780_common_fontsize
- hd44780_common_lines

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- this patch is squashed together from the former individual
  hd44780_common_ function patches
---
 drivers/auxdisplay/charlcd.c|  73 ++--
 drivers/auxdisplay/charlcd.h|  28 ++
 drivers/auxdisplay/hd44780.c|  14 +++
 drivers/auxdisplay/hd44780_common.c | 131 
 drivers/auxdisplay/hd44780_common.h |   9 ++
 drivers/auxdisplay/panel.c  |  21 +
 6 files changed, 249 insertions(+), 27 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 94f6b0afab13..281a3259c144 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -31,10 +31,6 @@
 #define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
 #define LCD_CMD_BLINK_ON   0x01/* Set blink on */
 
-#define LCD_CMD_SHIFT  0x10/* Shift cursor/display */
-#define LCD_CMD_DISPLAY_SHIFT  0x08/* Shift display instead of cursor */
-#define LCD_CMD_SHIFT_RIGHT0x04/* Shift display/cursor to the right */
-
 #define LCD_CMD_FUNCTION_SET   0x20/* Set function */
 #define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
 #define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
@@ -236,26 +232,44 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
switch (*esc) {
case 'D':   /* Display ON */
priv->flags |= LCD_FLAG_D;
+   if (priv->flags != oldflags)
+   lcd->ops->display(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'd':   /* Display OFF */
priv->flags &= ~LCD_FLAG_D;
+   if (priv->flags != oldflags)
+   lcd->ops->display(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case 'C':   /* Cursor ON */
priv->flags |= LCD_FLAG_C;
+   if (priv->flags != oldflags)
+   lcd->ops->cursor(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'c':   /* Cursor OFF */
priv->flags &= ~LCD_FLAG_C;
+   if (priv->flags != oldflags)
+   lcd->ops->cursor(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case 'B':   /* Blink ON */
priv->flags |= LCD_FLAG_B;
+   if (priv->flags != oldflags)
+   lcd->ops->blink(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'b':   /* Blink OFF */
priv->flags &= ~LCD_FLAG_B;
+   if (priv->flags != oldflags)
+   lcd->ops->blink(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case '+':   /* Back light ON */
@@ -272,47 +286,54 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'f':   /* Small Font */
priv->flags &= ~LCD_FLAG_F;
+   if (priv->flags != oldflags)
+   lcd->ops->fontsize(lcd, CHARLCD_FONTSIZE_SMALL);
+
processed = 1;
break;
case 'F':   /* Large Font */
priv->flags |= LCD_FLAG_F;
+   if (priv->flags != oldflags)
+   lcd->ops->fontsize(lcd, CHARLCD_FONTSIZE_LARGE);
+
processed = 1;
break;
case 'n':   /* One Line */
priv->flags &= ~LCD_FLAG_N;
+   if (priv->flags != oldflags)
+   lcd->ops->lines(lcd, CHARLCD_LINES_1);
+
processed = 1;
break;
case 'N':   /* Two Lines */
priv->flags |= LCD_FLAG_N;
+   if (priv->flags != oldflags)
+   lcd->ops->lines(lcd, CHARLCD_LINES_2);
+
processed = 1;
break;
case 'l':   /* Shift Cursor Left */
if (lcd->addr.x > 0) {
-   /* back one char if not at end of line */
-   if (lcd->addr.x < hdc->bwidth)
-   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   lcd->addr.x--;
+   if (!lcd->ops->shift_cursor(lcd, CHARLCD_SHIFT_

[PATCH v6 03/25] auxdisplay: Move hwidth and bwidth to struct hd44780_common

2020-11-03 Thread poeschel
From: Lars Poeschel 

hwidth is for the hardware buffer size and bwidth is for the buffer
width of one single line. This is specific to the hd44780 displays and
so it is moved out from charlcd to struct hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 40 -
 drivers/auxdisplay/charlcd.h|  6 ++--
 drivers/auxdisplay/hd44780.c| 24 +--
 drivers/auxdisplay/hd44780_common.c |  2 ++
 drivers/auxdisplay/hd44780_common.h |  5 
 drivers/auxdisplay/panel.c  | 45 +++--
 6 files changed, 67 insertions(+), 55 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 8aaee0fea9ab..02392336d7d3 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -21,9 +21,7 @@
 #include 
 
 #include "charlcd.h"
-
-#define DEFAULT_LCD_BWIDTH  40
-#define DEFAULT_LCD_HWIDTH  64
+#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
@@ -151,18 +149,19 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
 
/*
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = priv->addr.x < lcd->bwidth ? priv->addr.x & (lcd->hwidth - 1)
- : lcd->bwidth - 1;
+   addr = priv->addr.x < hdc->bwidth ? priv->addr.x & (hdc->hwidth - 1)
+ : hdc->bwidth - 1;
if (priv->addr.y & 1)
-   addr += lcd->hwidth;
+   addr += hdc->hwidth;
if (priv->addr.y & 2)
-   addr += lcd->bwidth;
+   addr += hdc->bwidth;
lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
@@ -178,21 +177,23 @@ static void charlcd_home(struct charlcd *lcd)
 static void charlcd_print(struct charlcd *lcd, char c)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
-   if (priv->addr.x < lcd->bwidth) {
+   if (priv->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
lcd->ops->write_data(lcd, c);
priv->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (priv->addr.x == lcd->bwidth)
+   if (priv->addr.x == hdc->bwidth)
charlcd_gotoxy(lcd);
}
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
 {
+   struct hd44780_common *hdc = lcd->drvdata;
int pos;
 
charlcd_home(lcd);
@@ -200,7 +201,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
if (lcd->ops->clear_fast)
lcd->ops->clear_fast(lcd);
else
-   for (pos = 0; pos < min(2, lcd->height) * lcd->hwidth; pos++)
+   for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
lcd->ops->write_data(lcd, ' ');
 
charlcd_home(lcd);
@@ -348,6 +349,7 @@ static bool parse_xy(const char *s, unsigned long *x, 
unsigned long *y)
 static inline int handle_lcd_special_code(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
/* LCD special codes */
 
@@ -413,7 +415,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
case 'l':   /* Shift Cursor Left */
if (priv->addr.x > 0) {
/* back one char if not at end of line */
-   if (priv->addr.x < lcd->bwidth)
+   if (priv->addr.x < hdc->bwidth)
lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
priv->addr.x--;
}
@@ -422,7 +424,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
case 'r':   /* shift cursor right */
if (priv->addr.x < lcd->width) {
/* allow the cursor to pass the end of the line */
-   if (priv->addr.x < (lcd->bwidth - 1))
+   if (priv->addr.x < (hdc->bwidth - 1))
lcd->ops->write_cmd(lcd,
LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
priv->addr.x++;
@@ -442,7 +444,7 @@ static inline int handle_lcd_special_code(struct

[PATCH v6 01/25] auxdisplay: Use an enum for charlcd backlight on/off ops

2020-11-03 Thread poeschel
From: Lars Poeschel 

We use an enum for calling the functions in charlcd, that turn the
backlight on or off. This enum is generic and can be used for other
charlcd turn on / turn off operations as well.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix a commit message typo: of -> on
---
 drivers/auxdisplay/charlcd.c | 2 +-
 drivers/auxdisplay/charlcd.h | 7 ++-
 drivers/auxdisplay/hd44780.c | 2 +-
 drivers/auxdisplay/panel.c   | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 5aee0f546351..8aaee0fea9ab 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -101,7 +101,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, int on)
+static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 00911ad0f3de..c66f038e5d2b 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -9,6 +9,11 @@
 #ifndef _CHARLCD_H
 #define _CHARLCD_H
 
+enum charlcd_onoff {
+   CHARLCD_OFF = 0,
+   CHARLCD_ON,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -30,7 +35,7 @@ struct charlcd_ops {
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
void (*clear_fast)(struct charlcd *lcd);
-   void (*backlight)(struct charlcd *lcd, int on);
+   void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 struct charlcd *charlcd_alloc(unsigned int drvdata_size);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index bcbe13092327..5982158557bb 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -37,7 +37,7 @@ struct hd44780 {
struct gpio_desc *pins[PIN_NUM];
 };
 
-static void hd44780_backlight(struct charlcd *lcd, int on)
+static void hd44780_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct hd44780 *hd = lcd->drvdata;
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 1c82d824ae00..de623ae219f1 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -708,7 +708,7 @@ static void lcd_send_serial(int byte)
 }
 
 /* turn the backlight on or off */
-static void lcd_backlight(struct charlcd *charlcd, int on)
+static void lcd_backlight(struct charlcd *charlcd, enum charlcd_onoff on)
 {
if (lcd.pins.bl == PIN_NONE)
return;
-- 
2.28.0



[PATCH v6 09/25] auxdisplay: provide hd44780_common_gotoxy

2020-11-03 Thread poeschel
From: Lars Poeschel 

Provide a hd44780_common_gotoxy function and a pointer in the ops for
charlcd to use to move the cursor.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 38 +
 drivers/auxdisplay/charlcd.h|  4 ++-
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 23 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 72ed004a8980..d6f971eea6ae 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -55,7 +55,7 @@
 
 #define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
 
-#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
+#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
 
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
@@ -140,33 +140,17 @@ void charlcd_poke(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(charlcd_poke);
 
-static void charlcd_gotoxy(struct charlcd *lcd)
-{
-   struct hd44780_common *hdc = lcd->drvdata;
-   unsigned int addr;
-
-   /*
-* we force the cursor to stay at the end of the
-* line if it wants to go farther
-*/
-   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
- : hdc->bwidth - 1;
-   if (lcd->addr.y & 1)
-   addr += hdc->hwidth;
-   if (lcd->addr.y & 2)
-   addr += hdc->bwidth;
-   hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
-}
-
 static void charlcd_home(struct charlcd *lcd)
 {
lcd->addr.x = 0;
lcd->addr.y = 0;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
+   struct hd44780_common *hdc = lcd->drvdata;
+
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
@@ -174,8 +158,8 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == lcd->width)
-   charlcd_gotoxy(lcd);
+   if (lcd->addr.x == hdc->bwidth)
+   lcd->ops->gotoxy(lcd);
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
@@ -440,7 +424,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
/* restore cursor position */
lcd->addr.x = xs;
lcd->addr.y = ys;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
processed = 1;
break;
}
@@ -499,7 +483,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
hdc->write_data(hdc, cgbytes[addr]);
 
/* ensures that we stop writing to CGRAM */
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
processed = 1;
break;
}
@@ -510,7 +494,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
/* If the command is valid, move to the new address */
if (parse_xy(esc, >addr.x, >addr.y))
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
 
/* Regardless of its validity, mark as processed */
processed = 1;
@@ -596,12 +580,12 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
 
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
break;
case '\r':
/* go to the beginning of the same line */
lcd->addr.x = 0;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
break;
case '\t':
/* print a space instead of the tab */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 94922e3c1c4c..f36cc80ce385 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -37,14 +37,16 @@ struct charlcd {
  * Optional.
  * @backlight: Turn backlight on or off. Optional.
  * @print: Print one character to the display at current cursor position.
- * The cursor is advanced by charlcd.
  * The buffered cursor position is advanced by charlcd. The cursor should not
  * wrap to th

[PATCH v6 25/25] auxdisplay: add a driver for lcd2s character display

2020-11-03 Thread poeschel
From: Lars Poeschel 

This driver allows to use a lcd2s 20x4 character display from Modtronix
engineering as an auxdisplay charlcd device.

Signed-off-by: Lars Poeschel 
---
Changes in v5:
- use hex_to_bin like in commit 3f03b6498 but for this file
Changes in v4:
- modtronix -> Modtronix
- Kconfig: remove "default n"
---
 drivers/auxdisplay/Kconfig  |  10 +
 drivers/auxdisplay/Makefile |   1 +
 drivers/auxdisplay/lcd2s.c  | 403 
 3 files changed, 414 insertions(+)
 create mode 100644 drivers/auxdisplay/lcd2s.c

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index aaf2d66357a1..a69623124a26 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -173,6 +173,16 @@ config HT16K33
  Say yes here to add support for Holtek HT16K33, RAM mapping 16*8
  LED controller driver with keyscan.
 
+config LCD2S
+   tristate "lcd2s 20x4 character display over I2C console"
+   depends on I2C
+   select CHARLCD
+   help
+ This is a driver that lets you use the lcd2s 20x4 character display
+ from Modtronix engineering as a console output device. The display
+ is a simple single color character display. You have to connect it
+ to an I2C bus.
+
 config ARM_CHARLCD
bool "ARM Ltd. Character LCD Driver"
depends on PLAT_VERSATILE
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index 7e8a8c3eb3c3..307771027c89 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_IMG_ASCII_LCD)   += img-ascii-lcd.o
 obj-$(CONFIG_HD44780)  += hd44780.o
 obj-$(CONFIG_HT16K33)  += ht16k33.o
 obj-$(CONFIG_PARPORT_PANEL)+= panel.o
+obj-$(CONFIG_LCD2S)+= lcd2s.o
diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
new file mode 100644
index ..cfa5f86deeef
--- /dev/null
+++ b/drivers/auxdisplay/lcd2s.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  console driver for LCD2S 4x20 character displays connected through i2c.
+ *  The display also has a spi interface, but the driver does not support
+ *  this yet.
+ *
+ *  This is a driver allowing you to use a LCD2S 4x20 from modtronix
+ *  engineering as auxdisplay character device.
+ *
+ *  (C) 2019 by Lemonage Software GmbH
+ *  Author: Lars Pöschel 
+ *  All rights reserved.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "charlcd.h"
+
+#define LCD2S_CMD_CUR_MOVES_FWD0x09
+#define LCD2S_CMD_CUR_BLINK_OFF0x10
+#define LCD2S_CMD_CUR_UL_OFF   0x11
+#define LCD2S_CMD_DISPLAY_OFF  0x12
+#define LCD2S_CMD_CUR_BLINK_ON 0x18
+#define LCD2S_CMD_CUR_UL_ON0x19
+#define LCD2S_CMD_DISPLAY_ON   0x1a
+#define LCD2S_CMD_BACKLIGHT_OFF0x20
+#define LCD2S_CMD_BACKLIGHT_ON 0x28
+#define LCD2S_CMD_WRITE0x80
+#define LCD2S_CMD_MOV_CUR_RIGHT0x83
+#define LCD2S_CMD_MOV_CUR_LEFT 0x84
+#define LCD2S_CMD_SHIFT_RIGHT  0x85
+#define LCD2S_CMD_SHIFT_LEFT   0x86
+#define LCD2S_CMD_SHIFT_UP 0x87
+#define LCD2S_CMD_SHIFT_DOWN   0x88
+#define LCD2S_CMD_CUR_ADDR 0x89
+#define LCD2S_CMD_CUR_POS  0x8a
+#define LCD2S_CMD_CUR_RESET0x8b
+#define LCD2S_CMD_CLEAR0x8c
+#define LCD2S_CMD_DEF_CUSTOM_CHAR  0x92
+#define LCD2S_CMD_READ_STATUS  0xd0
+
+#define LCD2S_CHARACTER_SIZE   8
+
+#define LCD2S_STATUS_BUF_MASK  0x7f
+
+struct lcd2s_data {
+   struct i2c_client *i2c;
+   struct charlcd *charlcd;
+};
+
+static s32 lcd2s_wait_buf_free(const struct i2c_client *client, int count)
+{
+   s32 status;
+
+   status = i2c_smbus_read_byte_data(client, LCD2S_CMD_READ_STATUS);
+   if (status < 0)
+   return status;
+
+   while ((status & LCD2S_STATUS_BUF_MASK) < count) {
+   mdelay(1);
+   status = i2c_smbus_read_byte_data(client,
+ LCD2S_CMD_READ_STATUS);
+   if (status < 0)
+   return status;
+   }
+   return 0;
+}
+
+static int lcd2s_i2c_master_send(const struct i2c_client *client,
+const char *buf, int count)
+{
+   s32 status;
+
+   status = lcd2s_wait_buf_free(client, count);
+   if (status < 0)
+   return status;
+
+   return i2c_master_send(client, buf, count);
+}
+
+static int lcd2s_i2c_smbus_write_byte(const struct i2c_client *client, u8 
value)
+{
+   s32 status;
+
+   status = lcd2s_wait_buf_free(client, 1);
+   if (status < 0)
+   return status;
+
+   return i2c_smbus_write_byte(client, value);
+}
+
+static int lcd2s_print(struct charlcd *lcd, int c)
+{
+  

[PATCH v6 21/25] auxdisplay: charlcd: replace last device specific stuff

2020-11-03 Thread poeschel
From: Lars Poeschel 

These are the last bits left in charlcd.c that are device specific and
they are removed now.
In detail this is:
* bwidth, which is the width of the display buffer per line. This is
  replaced by width of the display.
* hwidth, which is the size of the display buffer as a whole. This is
  replaced by looping all chars of a line by all lines.
* the hd44780_common header include can go away.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 077c01e87127..59f21401d6a9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -20,7 +20,6 @@
 #include 
 
 #include "charlcd.h"
-#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
@@ -112,8 +111,6 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
-
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
@@ -121,7 +118,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == hdc->bwidth)
+   if (lcd->addr.x == lcd->width)
lcd->ops->gotoxy(lcd);
 }
 
@@ -195,7 +192,6 @@ static bool parse_xy(const char *s, unsigned long *x, 
unsigned long *y)
 static inline int handle_lcd_special_code(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
 
/* LCD special codes */
 
@@ -323,7 +319,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
xs = lcd->addr.x;
ys = lcd->addr.y;
-   for (x = lcd->addr.x; x < hdc->bwidth; x++)
+   for (x = lcd->addr.x; x < lcd->width; x++)
lcd->ops->print(lcd, ' ');
 
/* restore cursor position */
@@ -366,7 +362,6 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 static void charlcd_write_char(struct charlcd *lcd, char c)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
 
/* first, we'll test if we're in escape mode */
if ((c != '\n') && priv->esc_seq.len >= 0) {
@@ -407,7 +402,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * flush the remainder of the current line and
 * go to the beginning of the next line
 */
-   for (; lcd->addr.x < hdc->bwidth; lcd->addr.x++)
+   for (; lcd->addr.x < lcd->width; lcd->addr.x++)
lcd->ops->print(lcd, ' ');
 
lcd->addr.x = 0;
-- 
2.28.0



Re: [PATCH v5 02/25] auxdisplay: Introduce hd44780_common.[ch]

2020-11-03 Thread Lars Poeschel
On Sat, Oct 31, 2020 at 10:26:30AM +0100, Miguel Ojeda wrote:
> Hi Lars,
> 
> On Thu, Oct 29, 2020 at 10:57 AM  wrote:
> >
> > diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
> > index 81757eeded68..a56171d1a1ba 100644
> > --- a/drivers/auxdisplay/Kconfig
> > +++ b/drivers/auxdisplay/Kconfig
> > @@ -14,12 +14,31 @@ menuconfig AUXDISPLAY
> >
> >   If you say N, all options in this submenu will be skipped and 
> > disabled.
> >
> > +config CHARLCD
> > +   tristate "Character LCD core support" if COMPILE_TEST
> > +   help
> > + This is the base system for character-based LCD displays.
> > + It makes no sense to have this alone, you select your display 
> > driver
> > + and if it needs the charlcd core, it will select it automatically.
> > + This is some character LCD core interface that multiple drivers 
> > can
> > + use.
> > +
> > +config HD44780_COMMON
> > +   tristate "Common functions for HD44780 (and compatibles) LCD 
> > displays" if COMPILE_TEST
> > +   help
> > + This is a module with the common symbols for HD44780 (and 
> > compatibles)
> > + displays. This is the code that multiple other modules use. It is 
> > not
> > + useful alone. If you have some sort of HD44780 compatible display,
> > + you very likely use this. It is selected automatically by 
> > selecting
> > + your concrete display.
> > +
> >  if AUXDISPLAY
> >
> 
> These two should be after `if AUXDISPLAY`, no? I noticed the menu is
> broken when I went to compile test this (the options appear outside
> and the auxdisplay menu is empty). Perhaps you don't use menuconfig so
> you didn't see it?

I did see it and had a look and did not spot anything obvious (to me).
So I put this aside as "This is supposed to be this way."

> Sorry I missed this in previous iterations...

No need to be sorry. In the end it's my fault. I fix this.

Regards,
Lars


Re: [PATCH 00/25] Make charlcd device independent

2020-10-29 Thread Lars Poeschel
This series was sent wrong. Should be v5. Drop this one.

Sorry and thanks,
Lars

On Thu, Oct 29, 2020 at 10:50:07AM +0100, poesc...@lemonage.de wrote:
> From: Lars Poeschel 
> 
> This tries to make charlcd device independent. At the moment hd44780
> device specific code is contained deep in charlcd. This moves this out
> into a hd44780_common module, where the two hd44780 drivers we have at
> the moment (hd44780 and panel) can use this from. The goal is that at
> the end other drivers can use the charlcd interface.
> I add one such driver for a modtronix lcd displau  with the last patch.
> I submitted this already some time ago, where the wish was so split
> this into smaller chunks what I try to do with this patchset.
> 
> This is v5 of the patchset. I address a few review comments with this.
> I fixed some typos, but more importantly Miguel spotted that I reverted
> commit 3f03b6498 ("auxdisplay: charlcd: Reuse hex_to_bin() instead of
> custom code") during rebasing. This is corrected now.
> 
> As a note to patch 23:
> This might slightly change behaviour.
> On hd44780 displays with one or two lines the previous implementation
> did still write characters to the buffer of the display even if they are
> currently not visible. The shift_display command could be used so set
> the "viewing window" to a new position in the buffer and then you could
> see the characters previously written.
> This described behaviour does not work for hd44780 displays with more
> than two display lines. There simply is not enough buffer.
> So the behaviour was a bit inconsistens across different displays.
> The new behaviour is to stop writing character at the end of a visible
> line, even if there would be room in the buffer. This allows us to have
> an easy implementation, that should behave equal on all supported
> displays. This is not hd44780 hardware dependent anymore.
> 
> Link: https://lore.kernel.org/lkml/20191016082430.5955-1-poesc...@lemonage.de/
> Link: 
> https://lore.kernel.org/lkml/CANiq72kS-u_Xd_m+2CQVh-JCncPf1XNXrXAZ=4z+mze8fwv...@mail.gmail.com/
> 
> Changes in v5:
> - patch 1: Fix a commit message typo: of -> on
> - patch 2: Remove some unnecessary newlines
> - patch 8: Fix some typos
> - patch 14: Fix commit message typo: it's -> its
> - patch 15: this patch is squashed together from the former individual
>   hd44780_common_ function patches
> - patch 16: combined two cleanup patches
> - patch 17: I did previously undo commit 3f03b6498 which was a mistake.
>   This is now corrected.
> - patch 24: Picked up Robs Reviewed-by
> - patch 25: use hex_to_bin like in commit 3f03b6498 but for the lcd2s.c
>   file
> 
> Changes in v4:
> - modtronix -> Modtronix in new lcd2s driver
> - Kconfig: remove "default n" in new lcd2s driver
> 
> Changes in v3:
> - Fix some typos in Kconfig stuff
> - Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
> - new patch to reduce display timeout
> - better patch description to why not move cursor beyond end of a line
> - Fixed make dt_binding_doc errors
> 
> Changes in v2:
> - split whole patch into many smaller chunks
> - device tree doc in yaml
> 
> Lars Poeschel (25):
>   auxdisplay: Use an enum for charlcd  backlight on/off ops
>   auxdisplay: Introduce hd44780_common.[ch]
>   auxdisplay: Move hwidth and bwidth to struct hd44780_common
>   auxdisplay: Move ifwidth to struct hd44780_common
>   auxdisplay: Move write_data pointer to hd44780_common
>   auxdisplay: Move write_cmd pointers to hd44780 drivers
>   auxdisplay: Move addr out of charlcd_priv
>   auxdisplay: hd44780_common_print
>   auxdisplay: provide hd44780_common_gotoxy
>   auxdisplay: add home to charlcd_ops
>   auxdisplay: Move clear_display to hd44780_common
>   auxdisplay: make charlcd_backlight visible to hd44780_common
>   auxdisplay: Make use of enum for backlight on / off
>   auxdisplay: Move init_display to hd44780_common
>   auxdisplay: implement various hd44780_common_ functions
>   auxdisplay: cleanup unnecessary hd44780 code in charlcd
>   auxdisplay: Move char redefine code to hd44780_common
>   auxdisplay: Call charlcd_backlight in place
>   auxdisplay: hd44780_common: Reduce clear_display timeout
>   auxdisplay: hd44780: Remove clear_fast
>   auxdisplay: charlcd: replace last device specific stuff
>   auxdisplay: Change gotoxy calling interface
>   auxdisplay: charlcd: Do not print chars at end of line
>   auxdisplay: lcd2s DT binding doc
>   auxdisplay: add a driver for lcd2s character display
> 
>  .../bindings/auxdisplay/modtronix,lcd2s.yaml  |  58 +++
>  .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
>  drivers/auxdisplay/Kconfig  

[PATCH v5 24/25] auxdisplay: lcd2s DT binding doc

2020-10-29 Thread poeschel
From: Lars Poeschel 

Add a binding doc for the modtronix lcd2s auxdisplay driver. It also
adds modtronix to the list of known vendor-prefixes.

Reviewed-by: Willy Tarreau 
Reviewed-by: Rob Herring 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Picked up Robs Reviewed-by
Changes in v3:
- Fixed make dt_binding_doc errors
Changes in v2:
- Adopted yaml based file format
---
 .../bindings/auxdisplay/modtronix,lcd2s.yaml  | 58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
 2 files changed, 60 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml

diff --git a/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml 
b/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
new file mode 100644
index ..a1d55a2634a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/auxdisplay/modtronix,lcd2s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Modtronix engineering LCD2S Character LCD Display
+
+maintainers:
+  - Lars Poeschel 
+
+description:
+  The LCD2S is a Character LCD Display manufactured by Modtronix Engineering.
+  The display supports a serial I2C and SPI interface. The driver currently
+  only supports the I2C interface.
+
+properties:
+  compatible:
+const: modtronix,lcd2s
+
+  reg:
+maxItems: 1
+description:
+  I2C bus address of the display.
+
+  display-height-chars:
+description: Height of the display, in character cells.
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 1
+maximum: 4
+
+  display-width-chars:
+description: Width of the display, in character cells.
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 16
+maximum: 20
+
+required:
+  - compatible
+  - reg
+  - display-height-chars
+  - display-width-chars
+
+additionalProperties: false
+
+examples:
+  - |
+i2c {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  lcd2s: auxdisplay@28 {
+compatible = "modtronix,lcd2s";
+reg = <0x28>;
+display-height-chars = <4>;
+display-width-chars = <20>;
+  };
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml 
b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 2735be1a8470..65f40ab5a87f 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -681,6 +681,8 @@ patternProperties:
 description: MiraMEMS Sensing Technology Co., Ltd.
   "^mitsubishi,.*":
 description: Mitsubishi Electric Corporation
+  "^modtronix,.*":
+description: Modtronix Engineering
   "^mosaixtech,.*":
 description: Mosaix Technologies, Inc.
   "^motorola,.*":
-- 
2.28.0



[PATCH v5 25/25] auxdisplay: add a driver for lcd2s character display

2020-10-29 Thread poeschel
From: Lars Poeschel 

This driver allows to use a lcd2s 20x4 character display from Modtronix
engineering as an auxdisplay charlcd device.

Signed-off-by: Lars Poeschel 
---
Changes in v5:
- use hex_to_bin like in commit 3f03b6498 but for this file
Changes in v4:
- modtronix -> Modtronix
- Kconfig: remove "default n"
---
 drivers/auxdisplay/Kconfig  |  10 +
 drivers/auxdisplay/Makefile |   1 +
 drivers/auxdisplay/lcd2s.c  | 403 
 3 files changed, 414 insertions(+)
 create mode 100644 drivers/auxdisplay/lcd2s.c

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index a56171d1a1ba..96c8cdfce48d 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -173,6 +173,16 @@ config HT16K33
  Say yes here to add support for Holtek HT16K33, RAM mapping 16*8
  LED controller driver with keyscan.
 
+config LCD2S
+   tristate "lcd2s 20x4 character display over I2C console"
+   depends on I2C
+   select CHARLCD
+   help
+ This is a driver that lets you use the lcd2s 20x4 character display
+ from Modtronix engineering as a console output device. The display
+ is a simple single color character display. You have to connect it
+ to an I2C bus.
+
 config ARM_CHARLCD
bool "ARM Ltd. Character LCD Driver"
depends on PLAT_VERSATILE
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index 7e8a8c3eb3c3..307771027c89 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_IMG_ASCII_LCD)   += img-ascii-lcd.o
 obj-$(CONFIG_HD44780)  += hd44780.o
 obj-$(CONFIG_HT16K33)  += ht16k33.o
 obj-$(CONFIG_PARPORT_PANEL)+= panel.o
+obj-$(CONFIG_LCD2S)+= lcd2s.o
diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
new file mode 100644
index ..cfa5f86deeef
--- /dev/null
+++ b/drivers/auxdisplay/lcd2s.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  console driver for LCD2S 4x20 character displays connected through i2c.
+ *  The display also has a spi interface, but the driver does not support
+ *  this yet.
+ *
+ *  This is a driver allowing you to use a LCD2S 4x20 from modtronix
+ *  engineering as auxdisplay character device.
+ *
+ *  (C) 2019 by Lemonage Software GmbH
+ *  Author: Lars Pöschel 
+ *  All rights reserved.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "charlcd.h"
+
+#define LCD2S_CMD_CUR_MOVES_FWD0x09
+#define LCD2S_CMD_CUR_BLINK_OFF0x10
+#define LCD2S_CMD_CUR_UL_OFF   0x11
+#define LCD2S_CMD_DISPLAY_OFF  0x12
+#define LCD2S_CMD_CUR_BLINK_ON 0x18
+#define LCD2S_CMD_CUR_UL_ON0x19
+#define LCD2S_CMD_DISPLAY_ON   0x1a
+#define LCD2S_CMD_BACKLIGHT_OFF0x20
+#define LCD2S_CMD_BACKLIGHT_ON 0x28
+#define LCD2S_CMD_WRITE0x80
+#define LCD2S_CMD_MOV_CUR_RIGHT0x83
+#define LCD2S_CMD_MOV_CUR_LEFT 0x84
+#define LCD2S_CMD_SHIFT_RIGHT  0x85
+#define LCD2S_CMD_SHIFT_LEFT   0x86
+#define LCD2S_CMD_SHIFT_UP 0x87
+#define LCD2S_CMD_SHIFT_DOWN   0x88
+#define LCD2S_CMD_CUR_ADDR 0x89
+#define LCD2S_CMD_CUR_POS  0x8a
+#define LCD2S_CMD_CUR_RESET0x8b
+#define LCD2S_CMD_CLEAR0x8c
+#define LCD2S_CMD_DEF_CUSTOM_CHAR  0x92
+#define LCD2S_CMD_READ_STATUS  0xd0
+
+#define LCD2S_CHARACTER_SIZE   8
+
+#define LCD2S_STATUS_BUF_MASK  0x7f
+
+struct lcd2s_data {
+   struct i2c_client *i2c;
+   struct charlcd *charlcd;
+};
+
+static s32 lcd2s_wait_buf_free(const struct i2c_client *client, int count)
+{
+   s32 status;
+
+   status = i2c_smbus_read_byte_data(client, LCD2S_CMD_READ_STATUS);
+   if (status < 0)
+   return status;
+
+   while ((status & LCD2S_STATUS_BUF_MASK) < count) {
+   mdelay(1);
+   status = i2c_smbus_read_byte_data(client,
+ LCD2S_CMD_READ_STATUS);
+   if (status < 0)
+   return status;
+   }
+   return 0;
+}
+
+static int lcd2s_i2c_master_send(const struct i2c_client *client,
+const char *buf, int count)
+{
+   s32 status;
+
+   status = lcd2s_wait_buf_free(client, count);
+   if (status < 0)
+   return status;
+
+   return i2c_master_send(client, buf, count);
+}
+
+static int lcd2s_i2c_smbus_write_byte(const struct i2c_client *client, u8 
value)
+{
+   s32 status;
+
+   status = lcd2s_wait_buf_free(client, 1);
+   if (status < 0)
+   return status;
+
+   return i2c_smbus_write_byte(client, value);
+}
+
+static int lcd2s_print(struct charlcd *lcd, int c)
+{
+  

[PATCH 02/25] auxdisplay: Introduce hd44780_common.[ch]

2020-10-29 Thread poeschel
From: Lars Poeschel 

There is some hd44780 specific code in charlcd and this code is used by
multiple drivers. To make charlcd independent from this device specific
code this has to be moved to a place where the multiple drivers can
share their common code. This common place is now introduced as
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Remove some unnecessary newlines

Changes in v3:
- Fix some typos
---
 drivers/auxdisplay/Kconfig  | 20 ++
 drivers/auxdisplay/Makefile |  1 +
 drivers/auxdisplay/hd44780.c| 43 +++--
 drivers/auxdisplay/hd44780_common.c | 19 +
 drivers/auxdisplay/hd44780_common.h |  7 +
 drivers/auxdisplay/panel.c  | 18 ++--
 6 files changed, 91 insertions(+), 17 deletions(-)
 create mode 100644 drivers/auxdisplay/hd44780_common.c
 create mode 100644 drivers/auxdisplay/hd44780_common.h

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 81757eeded68..a56171d1a1ba 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -14,12 +14,31 @@ menuconfig AUXDISPLAY
 
  If you say N, all options in this submenu will be skipped and 
disabled.
 
+config CHARLCD
+   tristate "Character LCD core support" if COMPILE_TEST
+   help
+ This is the base system for character-based LCD displays.
+ It makes no sense to have this alone, you select your display driver
+ and if it needs the charlcd core, it will select it automatically.
+ This is some character LCD core interface that multiple drivers can
+ use.
+
+config HD44780_COMMON
+   tristate "Common functions for HD44780 (and compatibles) LCD displays" 
if COMPILE_TEST
+   help
+ This is a module with the common symbols for HD44780 (and compatibles)
+ displays. This is the code that multiple other modules use. It is not
+ useful alone. If you have some sort of HD44780 compatible display,
+ you very likely use this. It is selected automatically by selecting
+ your concrete display.
+
 if AUXDISPLAY
 
 config HD44780
tristate "HD44780 Character LCD support"
depends on GPIOLIB || COMPILE_TEST
select CHARLCD
+   select HD44780_COMMON
help
  Enable support for Character LCDs using a HD44780 controller.
  The LCD is accessible through the /dev/lcd char device (10, 156).
@@ -168,6 +187,7 @@ menuconfig PARPORT_PANEL
tristate "Parallel port LCD/Keypad Panel support"
depends on PARPORT
select CHARLCD
+   select HD44780_COMMON
help
  Say Y here if you have an HD44780 or KS-0074 LCD connected to your
  parallel port. This driver also features 4 and 6-key keypads. The LCD
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index cf54b5efb07e..7e8a8c3eb3c3 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_CHARLCD)  += charlcd.o
+obj-$(CONFIG_HD44780_COMMON)   += hd44780_common.o
 obj-$(CONFIG_ARM_CHARLCD)  += arm-charlcd.o
 obj-$(CONFIG_KS0108)   += ks0108.o
 obj-$(CONFIG_CFAG12864B)   += cfag12864b.o cfag12864bfb.o
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 5982158557bb..271dba9cd108 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -15,6 +15,7 @@
 #include 
 
 #include "charlcd.h"
+#include "hd44780_common.h"
 
 enum hd44780_pin {
/* Order does matter due to writing to GPIO array subsets! */
@@ -179,8 +180,9 @@ static int hd44780_probe(struct platform_device *pdev)
struct device *dev = >dev;
unsigned int i, base;
struct charlcd *lcd;
+   struct hd44780_common *hdc;
struct hd44780 *hd;
-   int ifwidth, ret;
+   int ifwidth, ret = -ENOMEM;
 
/* Required pins */
ifwidth = gpiod_count(dev, "data");
@@ -198,31 +200,39 @@ static int hd44780_probe(struct platform_device *pdev)
return -EINVAL;
}
 
+   hdc = hd44780_common_alloc();
+   if (!hdc)
+   return -ENOMEM;
+
lcd = charlcd_alloc(sizeof(struct hd44780));
if (!lcd)
-   return -ENOMEM;
+   goto fail1;
 
-   hd = lcd->drvdata;
+   hd = kzalloc(sizeof(struct hd44780), GFP_KERNEL);
+   if (!hd)
+   goto fail2;
 
+   hdc->hd44780 = hd;
+   lcd->drvdata = hdc;
for (i = 0; i < ifwidth; i++) {
hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i,
  GPIOD_OUT_LOW);
if (IS_ERR(hd->pins[base + i])) {
ret = PTR_ERR(hd->pins[base + i]);
-   

[PATCH 00/25] Make charlcd device independent

2020-10-29 Thread poeschel
From: Lars Poeschel 

This tries to make charlcd device independent. At the moment hd44780
device specific code is contained deep in charlcd. This moves this out
into a hd44780_common module, where the two hd44780 drivers we have at
the moment (hd44780 and panel) can use this from. The goal is that at
the end other drivers can use the charlcd interface.
I add one such driver for a modtronix lcd displau  with the last patch.
I submitted this already some time ago, where the wish was so split
this into smaller chunks what I try to do with this patchset.

This is v5 of the patchset. I address a few review comments with this.
I fixed some typos, but more importantly Miguel spotted that I reverted
commit 3f03b6498 ("auxdisplay: charlcd: Reuse hex_to_bin() instead of
custom code") during rebasing. This is corrected now.

As a note to patch 23:
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used so set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistens across different displays.
The new behaviour is to stop writing character at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependent anymore.

Link: https://lore.kernel.org/lkml/20191016082430.5955-1-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/CANiq72kS-u_Xd_m+2CQVh-JCncPf1XNXrXAZ=4z+mze8fwv...@mail.gmail.com/

Changes in v5:
- patch 1: Fix a commit message typo: of -> on
- patch 2: Remove some unnecessary newlines
- patch 8: Fix some typos
- patch 14: Fix commit message typo: it's -> its
- patch 15: this patch is squashed together from the former individual
  hd44780_common_ function patches
- patch 16: combined two cleanup patches
- patch 17: I did previously undo commit 3f03b6498 which was a mistake.
  This is now corrected.
- patch 24: Picked up Robs Reviewed-by
- patch 25: use hex_to_bin like in commit 3f03b6498 but for the lcd2s.c
  file

Changes in v4:
- modtronix -> Modtronix in new lcd2s driver
- Kconfig: remove "default n" in new lcd2s driver

Changes in v3:
- Fix some typos in Kconfig stuff
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
- new patch to reduce display timeout
- better patch description to why not move cursor beyond end of a line
- Fixed make dt_binding_doc errors

Changes in v2:
- split whole patch into many smaller chunks
- device tree doc in yaml

Lars Poeschel (25):
  auxdisplay: Use an enum for charlcd  backlight on/off ops
  auxdisplay: Introduce hd44780_common.[ch]
  auxdisplay: Move hwidth and bwidth to struct hd44780_common
  auxdisplay: Move ifwidth to struct hd44780_common
  auxdisplay: Move write_data pointer to hd44780_common
  auxdisplay: Move write_cmd pointers to hd44780 drivers
  auxdisplay: Move addr out of charlcd_priv
  auxdisplay: hd44780_common_print
  auxdisplay: provide hd44780_common_gotoxy
  auxdisplay: add home to charlcd_ops
  auxdisplay: Move clear_display to hd44780_common
  auxdisplay: make charlcd_backlight visible to hd44780_common
  auxdisplay: Make use of enum for backlight on / off
  auxdisplay: Move init_display to hd44780_common
  auxdisplay: implement various hd44780_common_ functions
  auxdisplay: cleanup unnecessary hd44780 code in charlcd
  auxdisplay: Move char redefine code to hd44780_common
  auxdisplay: Call charlcd_backlight in place
  auxdisplay: hd44780_common: Reduce clear_display timeout
  auxdisplay: hd44780: Remove clear_fast
  auxdisplay: charlcd: replace last device specific stuff
  auxdisplay: Change gotoxy calling interface
  auxdisplay: charlcd: Do not print chars at end of line
  auxdisplay: lcd2s DT binding doc
  auxdisplay: add a driver for lcd2s character display

 .../bindings/auxdisplay/modtronix,lcd2s.yaml  |  58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 drivers/auxdisplay/Kconfig|  30 ++
 drivers/auxdisplay/Makefile   |   2 +
 drivers/auxdisplay/charlcd.c  | 412 +-
 drivers/auxdisplay/charlcd.h  |  86 +++-
 drivers/auxdisplay/hd44780.c  | 120 +++--
 drivers/auxdisplay/hd44780_common.c   | 361 +++
 drivers/auxdisplay/hd44780_common.h   |  33 ++
 drivers/auxdisplay/lcd2s.c| 403 +
 drivers/auxdisplay/panel.c| 180 
 11 files changed, 1237 insertions(+), 450 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/auxdisplay/m

[PATCH 01/25] auxdisplay: Use an enum for charlcd backlight on/off ops

2020-10-29 Thread poeschel
From: Lars Poeschel 

We use an enum for calling the functions in charlcd, that turn the
backlight on or off. This enum is generic and can be used for other
charlcd turn on / turn off operations as well.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix a commit message typo: of -> on
---
 drivers/auxdisplay/charlcd.c | 2 +-
 drivers/auxdisplay/charlcd.h | 7 ++-
 drivers/auxdisplay/hd44780.c | 2 +-
 drivers/auxdisplay/panel.c   | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 5aee0f546351..8aaee0fea9ab 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -101,7 +101,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, int on)
+static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 00911ad0f3de..c66f038e5d2b 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -9,6 +9,11 @@
 #ifndef _CHARLCD_H
 #define _CHARLCD_H
 
+enum charlcd_onoff {
+   CHARLCD_OFF = 0,
+   CHARLCD_ON,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -30,7 +35,7 @@ struct charlcd_ops {
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
void (*clear_fast)(struct charlcd *lcd);
-   void (*backlight)(struct charlcd *lcd, int on);
+   void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 struct charlcd *charlcd_alloc(unsigned int drvdata_size);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index bcbe13092327..5982158557bb 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -37,7 +37,7 @@ struct hd44780 {
struct gpio_desc *pins[PIN_NUM];
 };
 
-static void hd44780_backlight(struct charlcd *lcd, int on)
+static void hd44780_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct hd44780 *hd = lcd->drvdata;
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 1c82d824ae00..de623ae219f1 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -708,7 +708,7 @@ static void lcd_send_serial(int byte)
 }
 
 /* turn the backlight on or off */
-static void lcd_backlight(struct charlcd *charlcd, int on)
+static void lcd_backlight(struct charlcd *charlcd, enum charlcd_onoff on)
 {
if (lcd.pins.bl == PIN_NONE)
return;
-- 
2.28.0



[PATCH v5 08/25] auxdisplay: hd44780_common_print

2020-10-29 Thread poeschel
From: Lars Poeschel 

We create a hd44780_common_print function. It is derived from the
original charlcd_print. charlcd_print becomes a device independent print
function, that then only calls via its ops function pointers, into the
print function offered by drivers.

Reported-by: kernel test robot 
Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix some typos

Changes in v3:
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
---
 drivers/auxdisplay/charlcd.c| 28 +++-
 drivers/auxdisplay/charlcd.h| 12 
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 14 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 5 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 1b37d4bc38f9..72ed004a8980 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -167,18 +167,15 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
+   if (lcd->char_conv)
+   c = lcd->char_conv[(unsigned char)c];
 
-   if (lcd->addr.x < hdc->bwidth) {
-   if (lcd->char_conv)
-   c = lcd->char_conv[(unsigned char)c];
-   hdc->write_data(hdc, c);
+   if (!lcd->ops->print(lcd, c))
lcd->addr.x++;
 
-   /* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == hdc->bwidth)
-   charlcd_gotoxy(lcd);
-   }
+   /* prevents the cursor from wrapping onto the next line */
+   if (lcd->addr.x == lcd->width)
+   charlcd_gotoxy(lcd);
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
@@ -192,7 +189,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
lcd->ops->clear_fast(lcd);
else
for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
 
charlcd_home(lcd);
 }
@@ -433,12 +430,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'k': { /* kill end of line */
-   int x;
+   int x, xs, ys;
 
+   xs = lcd->addr.x;
+   ys = lcd->addr.y;
for (x = lcd->addr.x; x < hdc->bwidth; x++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
 
/* restore cursor position */
+   lcd->addr.x = xs;
+   lcd->addr.y = ys;
charlcd_gotoxy(lcd);
processed = 1;
break;
@@ -591,7 +592,8 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * go to the beginning of the next line
 */
for (; lcd->addr.x < hdc->bwidth; lcd->addr.x++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
+
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
charlcd_gotoxy(lcd);
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index ff4896af2189..94922e3c1c4c 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -30,9 +30,21 @@ struct charlcd {
void *drvdata;
 };
 
+/**
+ * struct charlcd_ops - Functions used by charlcd. Drivers have to implement
+ * these.
+ * @clear_fast: Clear the whole display and set cursor to position 0, 0.
+ * Optional.
+ * @backlight: Turn backlight on or off. Optional.
+ * @print: Print one character to the display at current cursor position.
+ * The cursor is advanced by charlcd.
+ * The buffered cursor position is advanced by charlcd. The cursor should not
+ * wrap to the next line at the end of a line.
+ */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
+   int (*print)(struct charlcd *lcd, int c);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index dc4738563298..9680bb611639 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -126,6 +126,7 @@ static void hd44780_write_data_gpio8(struct hd44780_common 
*hdc, int data)
 
 static const struct charlcd_ops hd44780_ops_gpio8 = {
.backlight  = hd44780_backlight,
+   .print  = hd44780_common_print,
 };
 
 /* Send a command to the LCD panel in 4 

[PATCH v5 03/25] auxdisplay: Move hwidth and bwidth to struct hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

hwidth is for the hardware buffer size and bwidth is for the buffer
width of one single line. This is specific to the hd44780 displays and
so it is moved out from charlcd to struct hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 40 -
 drivers/auxdisplay/charlcd.h|  6 ++--
 drivers/auxdisplay/hd44780.c| 24 +--
 drivers/auxdisplay/hd44780_common.c |  2 ++
 drivers/auxdisplay/hd44780_common.h |  5 
 drivers/auxdisplay/panel.c  | 45 +++--
 6 files changed, 67 insertions(+), 55 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 8aaee0fea9ab..02392336d7d3 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -21,9 +21,7 @@
 #include 
 
 #include "charlcd.h"
-
-#define DEFAULT_LCD_BWIDTH  40
-#define DEFAULT_LCD_HWIDTH  64
+#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
@@ -151,18 +149,19 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
 
/*
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = priv->addr.x < lcd->bwidth ? priv->addr.x & (lcd->hwidth - 1)
- : lcd->bwidth - 1;
+   addr = priv->addr.x < hdc->bwidth ? priv->addr.x & (hdc->hwidth - 1)
+ : hdc->bwidth - 1;
if (priv->addr.y & 1)
-   addr += lcd->hwidth;
+   addr += hdc->hwidth;
if (priv->addr.y & 2)
-   addr += lcd->bwidth;
+   addr += hdc->bwidth;
lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
@@ -178,21 +177,23 @@ static void charlcd_home(struct charlcd *lcd)
 static void charlcd_print(struct charlcd *lcd, char c)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
-   if (priv->addr.x < lcd->bwidth) {
+   if (priv->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
lcd->ops->write_data(lcd, c);
priv->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (priv->addr.x == lcd->bwidth)
+   if (priv->addr.x == hdc->bwidth)
charlcd_gotoxy(lcd);
}
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
 {
+   struct hd44780_common *hdc = lcd->drvdata;
int pos;
 
charlcd_home(lcd);
@@ -200,7 +201,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
if (lcd->ops->clear_fast)
lcd->ops->clear_fast(lcd);
else
-   for (pos = 0; pos < min(2, lcd->height) * lcd->hwidth; pos++)
+   for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
lcd->ops->write_data(lcd, ' ');
 
charlcd_home(lcd);
@@ -348,6 +349,7 @@ static bool parse_xy(const char *s, unsigned long *x, 
unsigned long *y)
 static inline int handle_lcd_special_code(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
/* LCD special codes */
 
@@ -413,7 +415,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
case 'l':   /* Shift Cursor Left */
if (priv->addr.x > 0) {
/* back one char if not at end of line */
-   if (priv->addr.x < lcd->bwidth)
+   if (priv->addr.x < hdc->bwidth)
lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
priv->addr.x--;
}
@@ -422,7 +424,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
case 'r':   /* shift cursor right */
if (priv->addr.x < lcd->width) {
/* allow the cursor to pass the end of the line */
-   if (priv->addr.x < (lcd->bwidth - 1))
+   if (priv->addr.x < (hdc->bwidth - 1))
lcd->ops->write_cmd(lcd,
LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
priv->addr.x++;
@@ -442,7 +444,7 @@ static inline int handle_lcd_special_code(struct

[PATCH v5 06/25] auxdisplay: Move write_cmd pointers to hd44780 drivers

2020-10-29 Thread poeschel
From: Lars Poeschel 

The write_cmd function is used to send commands to hd44780 displays.
The individual hd44780 drivers then implement their appropriate way of
doing this with their supported displays. So we move this pointer so
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 45 +++--
 drivers/auxdisplay/charlcd.h|  5 
 drivers/auxdisplay/hd44780.c| 15 --
 drivers/auxdisplay/hd44780_common.h |  3 ++
 drivers/auxdisplay/panel.c  | 12 
 5 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index df54078656c1..ce6622f71c34 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -162,7 +162,7 @@ static void charlcd_gotoxy(struct charlcd *lcd)
addr += hdc->hwidth;
if (priv->addr.y & 2)
addr += hdc->bwidth;
-   lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
+   hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
@@ -211,8 +211,9 @@ static void charlcd_clear_fast(struct charlcd *lcd)
 static void charlcd_clear_display(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
-   lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR);
+   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
priv->addr.x = 0;
priv->addr.y = 0;
/* we must wait a few milliseconds (15) */
@@ -221,7 +222,7 @@ static void charlcd_clear_display(struct charlcd *lcd)
 
 static int charlcd_init_display(struct charlcd *lcd)
 {
-   void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
+   void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
u8 init;
@@ -241,25 +242,25 @@ static int charlcd_init_display(struct charlcd *lcd)
init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
if (hdc->ifwidth == 4) {
init >>= 4;
-   write_cmd_raw = lcd->ops->write_cmd_raw4;
+   write_cmd_raw = hdc->write_cmd_raw4;
} else {
-   write_cmd_raw = lcd->ops->write_cmd;
+   write_cmd_raw = hdc->write_cmd;
}
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
 
if (hdc->ifwidth == 4) {
/* Switch to 4-bit mode, 1 line, small fonts */
-   lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
+   hdc->write_cmd_raw4(hdc, LCD_CMD_FUNCTION_SET >> 4);
long_sleep(10);
}
 
/* set font height and lines number */
-   lcd->ops->write_cmd(lcd,
+   hdc->write_cmd(hdc,
LCD_CMD_FUNCTION_SET |
((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
@@ -267,10 +268,10 @@ static int charlcd_init_display(struct charlcd *lcd)
long_sleep(10);
 
/* display off, cursor off, blink off */
-   lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CTRL);
+   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CTRL);
long_sleep(10);
 
-   lcd->ops->write_cmd(lcd,
+   hdc->write_cmd(hdc,
LCD_CMD_DISPLAY_CTRL |  /* set display mode */
((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
@@ -281,7 +282,7 @@ static int charlcd_init_display(struct charlcd *lcd)
long_sleep(10);
 
/* entry mode set : increment, cursor shifting */
-   lcd->ops->write_cmd(lcd, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
+   hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
 
charlcd_clear_display(lcd);
return 0;
@@ -417,7 +418,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (priv->addr.x > 0) {
/* back one char if not at end of line */
if (priv->addr.x < hdc->bwidth)
-   lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
+   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
priv->addr.x--;
}
processed = 1;
@@ -426,18 +427,18 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (priv->addr.x < lcd-

[PATCH v5 09/25] auxdisplay: provide hd44780_common_gotoxy

2020-10-29 Thread poeschel
From: Lars Poeschel 

Provide a hd44780_common_gotoxy function and a pointer in the ops for
charlcd to use to move the cursor.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 38 +
 drivers/auxdisplay/charlcd.h|  4 ++-
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 23 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 72ed004a8980..d6f971eea6ae 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -55,7 +55,7 @@
 
 #define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
 
-#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
+#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
 
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
@@ -140,33 +140,17 @@ void charlcd_poke(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(charlcd_poke);
 
-static void charlcd_gotoxy(struct charlcd *lcd)
-{
-   struct hd44780_common *hdc = lcd->drvdata;
-   unsigned int addr;
-
-   /*
-* we force the cursor to stay at the end of the
-* line if it wants to go farther
-*/
-   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
- : hdc->bwidth - 1;
-   if (lcd->addr.y & 1)
-   addr += hdc->hwidth;
-   if (lcd->addr.y & 2)
-   addr += hdc->bwidth;
-   hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
-}
-
 static void charlcd_home(struct charlcd *lcd)
 {
lcd->addr.x = 0;
lcd->addr.y = 0;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
+   struct hd44780_common *hdc = lcd->drvdata;
+
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
@@ -174,8 +158,8 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == lcd->width)
-   charlcd_gotoxy(lcd);
+   if (lcd->addr.x == hdc->bwidth)
+   lcd->ops->gotoxy(lcd);
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
@@ -440,7 +424,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
/* restore cursor position */
lcd->addr.x = xs;
lcd->addr.y = ys;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
processed = 1;
break;
}
@@ -499,7 +483,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
hdc->write_data(hdc, cgbytes[addr]);
 
/* ensures that we stop writing to CGRAM */
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
processed = 1;
break;
}
@@ -510,7 +494,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
/* If the command is valid, move to the new address */
if (parse_xy(esc, >addr.x, >addr.y))
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
 
/* Regardless of its validity, mark as processed */
processed = 1;
@@ -596,12 +580,12 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
 
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
break;
case '\r':
/* go to the beginning of the same line */
lcd->addr.x = 0;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
break;
case '\t':
/* print a space instead of the tab */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 94922e3c1c4c..f36cc80ce385 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -37,14 +37,16 @@ struct charlcd {
  * Optional.
  * @backlight: Turn backlight on or off. Optional.
  * @print: Print one character to the display at current cursor position.
- * The cursor is advanced by charlcd.
  * The buffered cursor position is advanced by charlcd. The cursor should not
  * wrap to th

[PATCH v5 15/25] auxdisplay: implement various hd44780_common_ functions

2020-10-29 Thread poeschel
From: Lars Poeschel 

This implements various hd44780_common_ functions for hd44780 compatible
display drivers to use. charlcd then calls these functions through its
ops function pointer.
The functions namely are:
- hd44780_common_shift_cursor
- hd44780_common_display_shift
- hd44780_common_display
- hd44780_common_cursor
- hd44780_common_blink
- hd44780_common_fontsize
- hd44780_common_lines

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- this patch is squashed together from the former individual
  hd44780_common_ function patches
---
 drivers/auxdisplay/charlcd.c|  73 ++--
 drivers/auxdisplay/charlcd.h|  28 ++
 drivers/auxdisplay/hd44780.c|  14 +++
 drivers/auxdisplay/hd44780_common.c | 131 
 drivers/auxdisplay/hd44780_common.h |   9 ++
 drivers/auxdisplay/panel.c  |  21 +
 6 files changed, 249 insertions(+), 27 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 94f6b0afab13..281a3259c144 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -31,10 +31,6 @@
 #define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
 #define LCD_CMD_BLINK_ON   0x01/* Set blink on */
 
-#define LCD_CMD_SHIFT  0x10/* Shift cursor/display */
-#define LCD_CMD_DISPLAY_SHIFT  0x08/* Shift display instead of cursor */
-#define LCD_CMD_SHIFT_RIGHT0x04/* Shift display/cursor to the right */
-
 #define LCD_CMD_FUNCTION_SET   0x20/* Set function */
 #define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
 #define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
@@ -236,26 +232,44 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
switch (*esc) {
case 'D':   /* Display ON */
priv->flags |= LCD_FLAG_D;
+   if (priv->flags != oldflags)
+   lcd->ops->display(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'd':   /* Display OFF */
priv->flags &= ~LCD_FLAG_D;
+   if (priv->flags != oldflags)
+   lcd->ops->display(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case 'C':   /* Cursor ON */
priv->flags |= LCD_FLAG_C;
+   if (priv->flags != oldflags)
+   lcd->ops->cursor(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'c':   /* Cursor OFF */
priv->flags &= ~LCD_FLAG_C;
+   if (priv->flags != oldflags)
+   lcd->ops->cursor(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case 'B':   /* Blink ON */
priv->flags |= LCD_FLAG_B;
+   if (priv->flags != oldflags)
+   lcd->ops->blink(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'b':   /* Blink OFF */
priv->flags &= ~LCD_FLAG_B;
+   if (priv->flags != oldflags)
+   lcd->ops->blink(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case '+':   /* Back light ON */
@@ -272,47 +286,54 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'f':   /* Small Font */
priv->flags &= ~LCD_FLAG_F;
+   if (priv->flags != oldflags)
+   lcd->ops->fontsize(lcd, CHARLCD_FONTSIZE_SMALL);
+
processed = 1;
break;
case 'F':   /* Large Font */
priv->flags |= LCD_FLAG_F;
+   if (priv->flags != oldflags)
+   lcd->ops->fontsize(lcd, CHARLCD_FONTSIZE_LARGE);
+
processed = 1;
break;
case 'n':   /* One Line */
priv->flags &= ~LCD_FLAG_N;
+   if (priv->flags != oldflags)
+   lcd->ops->lines(lcd, CHARLCD_LINES_1);
+
processed = 1;
break;
case 'N':   /* Two Lines */
priv->flags |= LCD_FLAG_N;
+   if (priv->flags != oldflags)
+   lcd->ops->lines(lcd, CHARLCD_LINES_2);
+
processed = 1;
break;
case 'l':   /* Shift Cursor Left */
if (lcd->addr.x > 0) {
-   /* back one char if not at end of line */
-   if (lcd->addr.x < hdc->bwidth)
-   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   lcd->addr.x--;
+   if (!lcd->ops->shift_cursor(lcd, CHARLCD_SHIFT_

[PATCH v5 17/25] auxdisplay: Move char redefine code to hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

Take the code to redefine characters out of charlcd and move it to
hd44780_common, as this is hd44780 specific.
There is now a function hd44780_common_redefine_char that drivers use
and charlcd calls it through its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- I did previously undo commit 3f03b6498 which was a mistake. This is
  now corrected.
---
 drivers/auxdisplay/charlcd.c| 60 +++--
 drivers/auxdisplay/charlcd.h|  2 +
 drivers/auxdisplay/hd44780.c|  2 +
 drivers/auxdisplay/hd44780_common.c | 57 +++
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 ++
 6 files changed, 70 insertions(+), 55 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 29737c3e18f6..dca1b138a239 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -25,8 +25,6 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-#define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
-
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
 
@@ -344,61 +342,13 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
LCD_FLAG_C | LCD_FLAG_B;
processed = 1;
break;
-   case 'G': {
-   /* Generator : LGcx...xx; must have  between '0'
-* and '7', representing the numerical ASCII code of the
-* redefined character, and  a sequence of 16
-* hex digits representing 8 bytes for each character.
-* Most LCDs will only use 5 lower bits of the 7 first
-* bytes.
-*/
-
-   unsigned char cgbytes[8];
-   unsigned char cgaddr;
-   int cgoffset;
-   int shift;
-   char value;
-   int addr;
-
-   if (!strchr(esc, ';'))
-   break;
-
-   esc++;
-
-   cgaddr = *(esc++) - '0';
-   if (cgaddr > 7) {
+   case 'G':
+   if (lcd->ops->redefine_char)
+   processed = lcd->ops->redefine_char(lcd, esc);
+   else
processed = 1;
-   break;
-   }
-
-   cgoffset = 0;
-   shift = 0;
-   value = 0;
-   while (*esc && cgoffset < 8) {
-   int half;
-
-   shift ^= 4;
-
-   half = hex_to_bin(*esc++);
-   if (half < 0)
-   continue;
-
-   value |= half << shift;
-   if (shift == 0) {
-   cgbytes[cgoffset++] = value;
-   value = 0;
-   }
-   }
-
-   hdc->write_cmd(hdc, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
-   for (addr = 0; addr < cgoffset; addr++)
-   hdc->write_data(hdc, cgbytes[addr]);
-
-   /* ensures that we stop writing to CGRAM */
-   lcd->ops->gotoxy(lcd);
-   processed = 1;
break;
-   }
+
case 'x':   /* gotoxy : LxXXX[yYYY]; */
case 'y':   /* gotoxy : LyYYY[xXXX]; */
if (priv->esc_seq.buf[priv->esc_seq.len - 1] != ';')
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5a89bdeb659a..3339e8c2554e 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -75,6 +75,7 @@ struct charlcd {
  * @cursor: Turn cursor on or off.
  * @blink: Turn cursor blink on or off.
  * @lines: One or two lines.
+ * @redefine_char: Redefine the actual pixel matrix of character.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -91,6 +92,7 @@ struct charlcd_ops {
int (*blink)(struct charlcd *lcd, enum charlcd_onoff on);
int (*fontsize)(struct charlcd *lcd, enum charlcd_fontsize size);
int (*lines)(struct charlcd *lcd, enum charlcd_lines lines);
+   int (*redefine_char)(struct charlcd *lcd, char *esc);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 7b7b28d72198..2e5e7c993933 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -138,6 +138,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.blink  = hd44780_common_blink,
.fontsize   = hd44780_common_fontsize,
.lines  = hd44780_common_lines,
+   .redef

[PATCH v5 05/25] auxdisplay: Move write_data pointer to hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

This moves the write_data function pointer from struct charlcd_ops to
struct hd44780_common. This is the function that actually writes the
character to the display. This hd44780 hardware specific function is
used by two drivers at the moment.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 12 ++--
 drivers/auxdisplay/charlcd.h|  1 -
 drivers/auxdisplay/hd44780.c| 16 +---
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  | 12 ++--
 5 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 59e0a815bf3d..df54078656c1 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -182,7 +182,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
if (priv->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
-   lcd->ops->write_data(lcd, c);
+   hdc->write_data(hdc, c);
priv->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
@@ -202,7 +202,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
lcd->ops->clear_fast(lcd);
else
for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
 
charlcd_home(lcd);
 }
@@ -446,7 +446,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
int x;
 
for (x = priv->addr.x; x < hdc->bwidth; x++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
 
/* restore cursor position */
charlcd_gotoxy(lcd);
@@ -505,7 +505,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
for (addr = 0; addr < cgoffset; addr++)
-   lcd->ops->write_data(lcd, cgbytes[addr]);
+   hdc->write_data(hdc, cgbytes[addr]);
 
/* ensures that we stop writing to CGRAM */
charlcd_gotoxy(lcd);
@@ -587,7 +587,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
priv->addr.x--;
}
/* replace with a space */
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
/* back one char again */
lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
break;
@@ -601,7 +601,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * go to the beginning of the next line
 */
for (; priv->addr.x < hdc->bwidth; priv->addr.x++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
priv->addr.x = 0;
priv->addr.y = (priv->addr.y + 1) % lcd->height;
charlcd_gotoxy(lcd);
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5dce9dd36562..fba4f2cd42c4 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -27,7 +27,6 @@ struct charlcd {
 struct charlcd_ops {
/* Required */
void (*write_cmd)(struct charlcd *lcd, int cmd);
-   void (*write_data)(struct charlcd *lcd, int data);
 
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index f6786239c36f..922f0e0d2e6d 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -115,9 +115,8 @@ static void hd44780_write_cmd_gpio8(struct charlcd *lcd, 
int cmd)
 }
 
 /* Send data to the LCD panel in 8 bit GPIO mode */
-static void hd44780_write_data_gpio8(struct charlcd *lcd, int data)
+static void hd44780_write_data_gpio8(struct hd44780_common *hdc, int data)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
struct hd44780 *hd = hdc->hd44780;
 
hd44780_write_gpio8(hd, data, 1);
@@ -128,7 +127,6 @@ static void hd44780_write_data_gpio8(struct charlcd *lcd, 
int data)
 
 static const struct charlcd_ops hd44780_ops_gpio8 = {
.write_cmd  = hd44780_write_cmd_gpio8,
-   .write_data = hd44780_write_data_gpio8,
.backlight  = hd44780_backlight,
 };
 
@@ -163,9 +161,8 @@ static void hd44780_write_cmd_raw_gpio4(struct charl

[PATCH v5 13/25] auxdisplay: Make use of enum for backlight on / off

2020-10-29 Thread poeschel
From: Lars Poeschel 

To turn the backlight on or off use our new enum CHARLCD_ON /
CHARLCD_OFF.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 154419513186..9631f70e8128 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -115,7 +115,7 @@ static void charlcd_bl_off(struct work_struct *work)
if (priv->bl_tempo) {
priv->bl_tempo = false;
if (!(priv->flags & LCD_FLAG_L))
-   priv->lcd.ops->backlight(>lcd, 0);
+   priv->lcd.ops->backlight(>lcd, CHARLCD_OFF);
}
mutex_unlock(>bl_tempo_lock);
 }
@@ -132,7 +132,7 @@ void charlcd_poke(struct charlcd *lcd)
 
mutex_lock(>bl_tempo_lock);
if (!priv->bl_tempo && !(priv->flags & LCD_FLAG_L))
-   lcd->ops->backlight(lcd, 1);
+   lcd->ops->backlight(lcd, CHARLCD_ON);
priv->bl_tempo = true;
schedule_delayed_work(>bl_work, LCD_BL_TEMPO_PERIOD * HZ);
mutex_unlock(>bl_tempo_lock);
@@ -829,7 +829,7 @@ int charlcd_unregister(struct charlcd *lcd)
the_charlcd = NULL;
if (lcd->ops->backlight) {
cancel_delayed_work_sync(>bl_work);
-   priv->lcd.ops->backlight(>lcd, 0);
+   priv->lcd.ops->backlight(>lcd, CHARLCD_OFF);
}
 
return 0;
-- 
2.28.0



[PATCH v5 14/25] auxdisplay: Move init_display to hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

The init_display function is moved over to hd44780_common. charlcd uses
it via its ops function pointer and drivers initialize the ops with the
common hd44780_common_init_display function.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix commit message typo: it's -> its
---
 drivers/auxdisplay/charlcd.c| 95 ++---
 drivers/auxdisplay/charlcd.h|  9 +++
 drivers/auxdisplay/hd44780.c|  2 +
 drivers/auxdisplay/hd44780_common.c | 88 ++
 drivers/auxdisplay/hd44780_common.h |  2 +
 drivers/auxdisplay/panel.c  |  3 +
 6 files changed, 110 insertions(+), 89 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 9631f70e8128..94f6b0afab13 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -8,7 +8,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -26,17 +25,7 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-#define LCD_FLAG_B 0x0004  /* Blink on */
-#define LCD_FLAG_C 0x0008  /* Cursor on */
-#define LCD_FLAG_D 0x0010  /* Display on */
-#define LCD_FLAG_F 0x0020  /* Large font mode */
-#define LCD_FLAG_N 0x0040  /* 2-rows mode */
-#define LCD_FLAG_L 0x0080  /* Backlight enabled */
-
 /* LCD commands */
-#define LCD_CMD_ENTRY_MODE 0x04/* Set entry mode */
-#define LCD_CMD_CURSOR_INC 0x02/* Increment cursor */
-
 #define LCD_CMD_DISPLAY_CTRL   0x08/* Display control */
 #define LCD_CMD_DISPLAY_ON 0x04/* Set display on */
 #define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
@@ -84,12 +73,6 @@ struct charlcd_priv {
 /* Device single-open policy control */
 static atomic_t charlcd_available = ATOMIC_INIT(1);
 
-/* sleeps that many milliseconds with a reschedule */
-static void long_sleep(int ms)
-{
-   schedule_timeout_interruptible(msecs_to_jiffies(ms));
-}
-
 /* turn the backlight on or off */
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
@@ -177,76 +160,6 @@ static void charlcd_clear_fast(struct charlcd *lcd)
charlcd_home(lcd);
 }
 
-static int charlcd_init_display(struct charlcd *lcd)
-{
-   void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
-   u8 init;
-
-   if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
-   return -EINVAL;
-
-   priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
- LCD_FLAG_C | LCD_FLAG_B;
-
-   long_sleep(20); /* wait 20 ms after power-up for the paranoid */
-
-   /*
-* 8-bit mode, 1 line, small fonts; let's do it 3 times, to make sure
-* the LCD is in 8-bit mode afterwards
-*/
-   init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
-   if (hdc->ifwidth == 4) {
-   init >>= 4;
-   write_cmd_raw = hdc->write_cmd_raw4;
-   } else {
-   write_cmd_raw = hdc->write_cmd;
-   }
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-
-   if (hdc->ifwidth == 4) {
-   /* Switch to 4-bit mode, 1 line, small fonts */
-   hdc->write_cmd_raw4(hdc, LCD_CMD_FUNCTION_SET >> 4);
-   long_sleep(10);
-   }
-
-   /* set font height and lines number */
-   hdc->write_cmd(hdc,
-   LCD_CMD_FUNCTION_SET |
-   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-   ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
-   ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
-   long_sleep(10);
-
-   /* display off, cursor off, blink off */
-   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CTRL);
-   long_sleep(10);
-
-   hdc->write_cmd(hdc,
-   LCD_CMD_DISPLAY_CTRL |  /* set display mode */
-   ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
-   ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
-   ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
-
-   charlcd_backlight(lcd, (priv->flags & LCD_FLAG_L) ? 1 : 0);
-
-   long_sleep(10);
-
-   /* entry mode set : increment, cursor shifting */
-   hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
-
-   lcd->ops->clear_display(lcd);
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   return 0;
-}
-
 /*
  * Parses a movement command of the form "(.*);", where the group can be
  * any number of subcommands of the form "(x|

[PATCH v5 10/25] auxdisplay: add home to charlcd_ops

2020-10-29 Thread poeschel
From: Lars Poeschel 

This adds a home function to the charlcd_ops struct and offer an
implementation for hd44780_common. This implementation is used by our
two hd44780 drivers. This is to make charlcd device independent.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 2 +-
 drivers/auxdisplay/charlcd.h| 3 +++
 drivers/auxdisplay/hd44780.c| 2 ++
 drivers/auxdisplay/hd44780_common.c | 8 
 drivers/auxdisplay/hd44780_common.h | 1 +
 drivers/auxdisplay/panel.c  | 3 +++
 6 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index d6f971eea6ae..44dd6e02eaf9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -144,7 +144,7 @@ static void charlcd_home(struct charlcd *lcd)
 {
lcd->addr.x = 0;
lcd->addr.y = 0;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->home(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index f36cc80ce385..236fd0e9e8ab 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -41,12 +41,15 @@ struct charlcd {
  * wrap to the next line at the end of a line.
  * @gotoxy: Set cursor to x, y. The x and y values to set the cursor to are
  * previously set in addr.x and addr.y by charlcd.
+ * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
+ * charlcd prior to calling this function.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
+   int (*home)(struct charlcd *lcd);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 4d9478f6e5ff..b0893ea49165 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -128,6 +128,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.backlight  = hd44780_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -173,6 +174,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.backlight  = hd44780_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index f86eb2f27cee..ea62beada9d8 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -41,6 +41,14 @@ int hd44780_common_gotoxy(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_gotoxy);
 
+int hd44780_common_home(struct charlcd *lcd)
+{
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
+   return hd44780_common_gotoxy(lcd);
+}
+EXPORT_SYMBOL_GPL(hd44780_common_home);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index d8cbea4a8658..c91070ed931b 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -16,4 +16,5 @@ struct hd44780_common {
 
 int hd44780_common_print(struct charlcd *lcd, int c);
 int hd44780_common_gotoxy(struct charlcd *lcd);
+int hd44780_common_home(struct charlcd *lcd);
 struct hd44780_common *hd44780_common_alloc(void);
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 75894eacd12f..b1e874f07456 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -876,18 +876,21 @@ static const struct charlcd_ops charlcd_serial_ops = {
.clear_fast = lcd_clear_fast_s,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
.clear_fast = lcd_clear_fast_p8,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
.clear_fast = lcd_clear_fast_tilcd,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0



[PATCH v5 16/25] auxdisplay: cleanup unnecessary hd44780 code in charlcd

2020-10-29 Thread poeschel
From: Lars Poeschel 

This cleans up now unnecessary hd44780 specific code from charlcd. We
obsoleted this with the last patch. So another chunk of hd44780 specific
code can be dropped from charlcd.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- combined two cleanup patches
---
 drivers/auxdisplay/charlcd.c | 32 +---
 1 file changed, 1 insertion(+), 31 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 281a3259c144..29737c3e18f6 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -25,21 +25,8 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-/* LCD commands */
-#define LCD_CMD_DISPLAY_CTRL   0x08/* Display control */
-#define LCD_CMD_DISPLAY_ON 0x04/* Set display on */
-#define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
-#define LCD_CMD_BLINK_ON   0x01/* Set blink on */
-
-#define LCD_CMD_FUNCTION_SET   0x20/* Set function */
-#define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
-#define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
-#define LCD_CMD_FONT_5X10_DOTS 0x04/* Set char font to 5x10 dots */
-
 #define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
 
-#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
-
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
 
@@ -431,24 +418,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (oldflags == priv->flags)
return processed;
 
-   /* check whether one of B,C,D flags were changed */
-   if ((oldflags ^ priv->flags) &
-   (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
-   /* set display mode */
-   hdc->write_cmd(hdc,
-   LCD_CMD_DISPLAY_CTRL |
-   ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
-   ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
-   ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
-   /* check whether one of F,N flags was changed */
-   else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
-   hdc->write_cmd(hdc,
-   LCD_CMD_FUNCTION_SET |
-   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-   ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 
0) |
-   ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
-   /* check whether L flag was changed */
-   else if ((oldflags ^ priv->flags) & LCD_FLAG_L)
+   if ((oldflags ^ priv->flags) & LCD_FLAG_L)
charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
 
return processed;
-- 
2.28.0



[PATCH v5 19/25] auxdisplay: hd44780_common: Reduce clear_display timeout

2020-10-29 Thread poeschel
From: Lars Poeschel 

Digging in the hd44780 datasheet revealed that the timeout needed after
clearing the whole display is only 1,64ms not 15ms. So we can reduce
that timeout.

Link: https://lore.kernel.org/lkml/20200922092121.gg16...@1wt.eu/
Link: https://www.crystalfontz.com/controllers/Hitachi/HD44780/433/

Signed-off-by: Lars Poeschel 
---
Changes in v3:
- This patch is new in v3
---
 drivers/auxdisplay/hd44780_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index c528fb8e8808..bd93a4d3367e 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -83,8 +83,8 @@ int hd44780_common_clear_display(struct charlcd *lcd)
struct hd44780_common *hdc = lcd->drvdata;
 
hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   /* we must wait a few milliseconds (15) */
-   long_sleep(15);
+   /* datasheet says to wait 1,64 milliseconds */
+   long_sleep(2);
return 0;
 }
 EXPORT_SYMBOL_GPL(hd44780_common_clear_display);
-- 
2.28.0



[PATCH v5 18/25] auxdisplay: Call charlcd_backlight in place

2020-10-29 Thread poeschel
From: Lars Poeschel 

This moves the call to charlcd_backlight from the end of the switch
into the actual case statement that originates the change of the
backlight. This is more consistent to what is now found in this switch.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index dca1b138a239..0f0568a4bd35 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -259,10 +259,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case '+':   /* Back light ON */
priv->flags |= LCD_FLAG_L;
+   if (priv->flags != oldflags)
+   charlcd_backlight(lcd, CHARLCD_ON);
+
processed = 1;
break;
case '-':   /* Back light OFF */
priv->flags &= ~LCD_FLAG_L;
+   if (priv->flags != oldflags)
+   charlcd_backlight(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case '*':   /* Flash back light */
@@ -363,14 +369,6 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
}
 
-   /* TODO: This indent party here got ugly, clean it! */
-   /* Check whether one flag was changed */
-   if (oldflags == priv->flags)
-   return processed;
-
-   if ((oldflags ^ priv->flags) & LCD_FLAG_L)
-   charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
-
return processed;
 }
 
-- 
2.28.0



[PATCH v5 23/25] auxdisplay: charlcd: Do not print chars at end of line

2020-10-29 Thread poeschel
From: Lars Poeschel 

Skip printing characters at the end of a display line. This fits to the
behaviour we already had, that the cursor is nailed to last position of
a line.
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used so set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistens across different displays.
The new behaviour is to stop writing character at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependents anymore.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v3:
- Better patch description
---
 drivers/auxdisplay/charlcd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index ef10b5ca0e16..f43430e9dcee 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -111,6 +111,9 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
+   if (lcd->addr.x >= lcd->width)
+   return;
+
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
-- 
2.28.0



[PATCH v5 04/25] auxdisplay: Move ifwidth to struct hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

Move struct charlcd member ifwidth to our new struct hd44780_common.
ifwidth is hd44780 device specific and is used by two drivers at the
moment, so we move it to a common place, where both can use this.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 12 ++--
 drivers/auxdisplay/charlcd.h|  1 -
 drivers/auxdisplay/hd44780.c|  2 +-
 drivers/auxdisplay/hd44780_common.c |  1 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 5 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 02392336d7d3..59e0a815bf3d 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -223,9 +223,10 @@ static int charlcd_init_display(struct charlcd *lcd)
 {
void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
u8 init;
 
-   if (lcd->ifwidth != 4 && lcd->ifwidth != 8)
+   if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
return -EINVAL;
 
priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
@@ -238,7 +239,7 @@ static int charlcd_init_display(struct charlcd *lcd)
 * the LCD is in 8-bit mode afterwards
 */
init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
-   if (lcd->ifwidth == 4) {
+   if (hdc->ifwidth == 4) {
init >>= 4;
write_cmd_raw = lcd->ops->write_cmd_raw4;
} else {
@@ -251,7 +252,7 @@ static int charlcd_init_display(struct charlcd *lcd)
write_cmd_raw(lcd, init);
long_sleep(10);
 
-   if (lcd->ifwidth == 4) {
+   if (hdc->ifwidth == 4) {
/* Switch to 4-bit mode, 1 line, small fonts */
lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
long_sleep(10);
@@ -260,7 +261,7 @@ static int charlcd_init_display(struct charlcd *lcd)
/* set font height and lines number */
lcd->ops->write_cmd(lcd,
LCD_CMD_FUNCTION_SET |
-   ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
long_sleep(10);
@@ -543,7 +544,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
lcd->ops->write_cmd(lcd,
LCD_CMD_FUNCTION_SET |
-   ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 
0) |
((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
/* check whether L flag was changed */
@@ -794,7 +795,6 @@ struct charlcd *charlcd_alloc(void)
priv->esc_seq.len = -1;
 
lcd = >lcd;
-   lcd->ifwidth = 8;
 
return lcd;
 }
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 2a12d07705a3..5dce9dd36562 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -18,7 +18,6 @@ struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
 
-   int ifwidth;/* 4-bit or 8-bit (default) */
int height;
int width;
 
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 0603af8f2336..f6786239c36f 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -275,7 +275,7 @@ static int hd44780_probe(struct platform_device *pdev)
/* Optional properties */
device_property_read_u32(dev, "internal-buffer-width", >bwidth);
 
-   lcd->ifwidth = ifwidth;
+   hdc->ifwidth = ifwidth;
lcd->ops = ifwidth == 8 ? _ops_gpio8 : _ops_gpio4;
 
ret = charlcd_register(lcd);
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 3a05fd30cae0..4968461f0c4a 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -12,6 +12,7 @@ struct hd44780_common *hd44780_common_alloc(void)
if (!hd)
return NULL;
 
+   hd->ifwidth = 8;
hd->bwidth = DEFAULT_LCD_BWIDTH;
hd->hwidth = DEFAULT_LCD_HWIDTH;
return hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 9647d24c4490..54cbe5a489d7 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++

[PATCH v5 22/25] auxdisplay: Change gotoxy calling interface

2020-10-29 Thread poeschel
From: Lars Poeschel 

Change the calling interface for gotoxy from supplying the x and y
coordinates in the charlcd struct to explicitly supplying x and y in
the function arguments. This is more intuitive and allows for moving
the cursor to positions independent from the position saved in the
charlcd struct.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 10 +-
 drivers/auxdisplay/charlcd.h|  2 +-
 drivers/auxdisplay/hd44780_common.c | 15 ++-
 drivers/auxdisplay/hd44780_common.h |  2 +-
 4 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 59f21401d6a9..ef10b5ca0e16 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -119,7 +119,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
 
/* prevents the cursor from wrapping onto the next line */
if (lcd->addr.x == lcd->width)
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x - 1, lcd->addr.y);
 }
 
 static void charlcd_clear_display(struct charlcd *lcd)
@@ -325,7 +325,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
/* restore cursor position */
lcd->addr.x = xs;
lcd->addr.y = ys;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
processed = 1;
break;
}
@@ -349,7 +349,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
/* If the command is valid, move to the new address */
if (parse_xy(esc, >addr.x, >addr.y))
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
 
/* Regardless of its validity, mark as processed */
processed = 1;
@@ -407,12 +407,12 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
 
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
break;
case '\r':
/* go to the beginning of the same line */
lcd->addr.x = 0;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
break;
case '\t':
/* print a space instead of the tab */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index e7e9b12b1e99..eed80063a6d2 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -78,7 +78,7 @@ struct charlcd {
 struct charlcd_ops {
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
-   int (*gotoxy)(struct charlcd *lcd);
+   int (*gotoxy)(struct charlcd *lcd, unsigned int x, unsigned int y);
int (*home)(struct charlcd *lcd);
int (*clear_display)(struct charlcd *lcd);
int (*init_display)(struct charlcd *lcd);
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index bd93a4d3367e..3934c2eebf33 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -49,7 +49,7 @@ int hd44780_common_print(struct charlcd *lcd, int c)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_print);
 
-int hd44780_common_gotoxy(struct charlcd *lcd)
+int hd44780_common_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y)
 {
struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
@@ -58,11 +58,10 @@ int hd44780_common_gotoxy(struct charlcd *lcd)
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
- : hdc->bwidth - 1;
-   if (lcd->addr.y & 1)
+   addr = x < hdc->bwidth ? x & (hdc->hwidth - 1) : hdc->bwidth - 1;
+   if (y & 1)
addr += hdc->hwidth;
-   if (lcd->addr.y & 2)
+   if (y & 2)
addr += hdc->bwidth;
hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
return 0;
@@ -71,9 +70,7 @@ EXPORT_SYMBOL_GPL(hd44780_common_gotoxy);
 
 int hd44780_common_home(struct charlcd *lcd)
 {
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   return hd44780_common_gotoxy(lcd);
+   return hd44780_common_gotoxy(lcd, 0, 0);
 }
 EXPORT_SYMBOL_GPL(hd44780_common_home);
 
@@ -341,7 +338,7

[PATCH v5 21/25] auxdisplay: charlcd: replace last device specific stuff

2020-10-29 Thread poeschel
From: Lars Poeschel 

These are the last bits left in charlcd.c that are device specific and
they are removed now.
In detail this is:
* bwidth, which is the width of the display buffer per line. This is
  replaced by width of the display.
* hwidth, which is the size of the display buffer as a whole. This is
  replaced by looping all chars of a line by all lines.
* the hd44780_common header include can go away.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 077c01e87127..59f21401d6a9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -20,7 +20,6 @@
 #include 
 
 #include "charlcd.h"
-#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
@@ -112,8 +111,6 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
-
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
@@ -121,7 +118,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == hdc->bwidth)
+   if (lcd->addr.x == lcd->width)
lcd->ops->gotoxy(lcd);
 }
 
@@ -195,7 +192,6 @@ static bool parse_xy(const char *s, unsigned long *x, 
unsigned long *y)
 static inline int handle_lcd_special_code(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
 
/* LCD special codes */
 
@@ -323,7 +319,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
xs = lcd->addr.x;
ys = lcd->addr.y;
-   for (x = lcd->addr.x; x < hdc->bwidth; x++)
+   for (x = lcd->addr.x; x < lcd->width; x++)
lcd->ops->print(lcd, ' ');
 
/* restore cursor position */
@@ -366,7 +362,6 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 static void charlcd_write_char(struct charlcd *lcd, char c)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
 
/* first, we'll test if we're in escape mode */
if ((c != '\n') && priv->esc_seq.len >= 0) {
@@ -407,7 +402,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * flush the remainder of the current line and
 * go to the beginning of the next line
 */
-   for (; lcd->addr.x < hdc->bwidth; lcd->addr.x++)
+   for (; lcd->addr.x < lcd->width; lcd->addr.x++)
lcd->ops->print(lcd, ' ');
 
lcd->addr.x = 0;
-- 
2.28.0



[PATCH v5 12/25] auxdisplay: make charlcd_backlight visible to hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

hd44780_common wants to use the charlcd_backlight function, so make it
visible.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 3 ++-
 drivers/auxdisplay/charlcd.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index fc0daf4987d5..154419513186 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -91,7 +91,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
+void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
@@ -103,6 +103,7 @@ static void charlcd_backlight(struct charlcd *lcd, enum 
charlcd_onoff on)
lcd->ops->backlight(lcd, on);
mutex_unlock(>bl_tempo_lock);
 }
+EXPORT_SYMBOL_GPL(charlcd_backlight);
 
 static void charlcd_bl_off(struct work_struct *work)
 {
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index a6c32c4d1aac..a3210305cae7 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -56,6 +56,7 @@ struct charlcd_ops {
int (*clear_display)(struct charlcd *lcd);
 };
 
+void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
 struct charlcd *charlcd_alloc(void);
 void charlcd_free(struct charlcd *lcd);
 
-- 
2.28.0



[PATCH v5 20/25] auxdisplay: hd44780: Remove clear_fast

2020-10-29 Thread poeschel
From: Lars Poeschel 

We remove the hd44780_clear_fast (display) clear implementation. With
the new timeout the normal clear_display is reasonably fast. So there is
no need for a clear_fast anymore.

Link: https://lore.kernel.org/lkml/20200922092121.gg16...@1wt.eu/

Signed-off-by: Lars Poeschel 
---
Changes in v3:
- This patch is squashed together from 26, 27 and 28 from previous patch
  set:
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-27-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-28-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-29-poesc...@lemonage.de/

- Additionally this now removes clear_fast from charlcd_ops and from
  panel driver.
---
 drivers/auxdisplay/charlcd.c | 21 ---
 drivers/auxdisplay/charlcd.h |  7 ++--
 drivers/auxdisplay/panel.c   | 67 
 3 files changed, 8 insertions(+), 87 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 0f0568a4bd35..077c01e87127 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -125,20 +125,11 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->ops->gotoxy(lcd);
 }
 
-static void charlcd_clear_fast(struct charlcd *lcd)
+static void charlcd_clear_display(struct charlcd *lcd)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
-   int pos;
-
-   charlcd_home(lcd);
-
-   if (lcd->ops->clear_fast)
-   lcd->ops->clear_fast(lcd);
-   else
-   for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   lcd->ops->print(lcd, ' ');
-
-   charlcd_home(lcd);
+   lcd->ops->clear_display(lcd);
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
 }
 
 /*
@@ -409,7 +400,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
break;
case '\f':
/* quickly clear the display */
-   charlcd_clear_fast(lcd);
+   charlcd_clear_display(lcd);
break;
case '\n':
/*
@@ -448,7 +439,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 
if (!strcmp(priv->esc_seq.buf, "[2J")) {
/* clear the display */
-   charlcd_clear_fast(lcd);
+   charlcd_clear_display(lcd);
processed = 1;
} else if (!strcmp(priv->esc_seq.buf, "[H")) {
/* cursor to home */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 3339e8c2554e..e7e9b12b1e99 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -55,8 +55,6 @@ struct charlcd {
 /**
  * struct charlcd_ops - Functions used by charlcd. Drivers have to implement
  * these.
- * @clear_fast: Clear the whole display and set cursor to position 0, 0.
- * Optional.
  * @backlight: Turn backlight on or off. Optional.
  * @print: Print one character to the display at current cursor position.
  * The buffered cursor position is advanced by charlcd. The cursor should not
@@ -65,8 +63,8 @@ struct charlcd {
  * previously set in addr.x and addr.y by charlcd.
  * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
  * charlcd prior to calling this function.
- * @clear_display: Again clear the whole display, set the cursor to 0, 0. The
- * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
+ * @clear_display: Clear the whole display and set the cursor to 0, 0. The
+ * values in addr.x and addr.y are set to 0, 0 by charlcd after to calling this
  * function.
  * @init_display: Initialize the display.
  * @shift_cursor: Shift cursor left or right one position.
@@ -78,7 +76,6 @@ struct charlcd {
  * @redefine_char: Redefine the actual pixel matrix of character.
  */
 struct charlcd_ops {
-   void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index b0d2ae5b9be8..e07fadac281d 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -808,72 +808,7 @@ static void lcd_write_data_tilcd(struct hd44780_common 
*hdc, int data)
spin_unlock_irq(_lock);
 }
 
-/* fills the display with spaces and resets X/Y */
-static void lcd_clear_fast_s(struct charlcd *charlcd)
-{
-   struct hd44780_common *hdc = charlcd->drvdata;
-   int pos;
-
-   spin_lock_irq(_lock);
-   for (pos = 0; pos < charlcd->height * hdc->hwidth; pos++) {
-   lcd_send_serial(0x5F);  /* R/W=W, RS=1 */
-   lcd_send_serial(' ' & 

[PATCH v5 11/25] auxdisplay: Move clear_display to hd44780_common

2020-10-29 Thread poeschel
From: Lars Poeschel 

This moves the clear_display function from charlcd to hd44780_common.
This is one more step to make charlcd independent from device specific
code. The two hd44780 drivers use the new function from hd44780_common
and charlcd calls this function through its function pointer in its ops
structure.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 22 ++
 drivers/auxdisplay/charlcd.h|  4 
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 21 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 44dd6e02eaf9..fc0daf4987d5 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -34,8 +34,6 @@
 #define LCD_FLAG_L 0x0080  /* Backlight enabled */
 
 /* LCD commands */
-#define LCD_CMD_DISPLAY_CLEAR  0x01/* Clear entire display */
-
 #define LCD_CMD_ENTRY_MODE 0x04/* Set entry mode */
 #define LCD_CMD_CURSOR_INC 0x02/* Increment cursor */
 
@@ -178,18 +176,6 @@ static void charlcd_clear_fast(struct charlcd *lcd)
charlcd_home(lcd);
 }
 
-/* clears the display and resets X/Y */
-static void charlcd_clear_display(struct charlcd *lcd)
-{
-   struct hd44780_common *hdc = lcd->drvdata;
-
-   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   /* we must wait a few milliseconds (15) */
-   long_sleep(15);
-}
-
 static int charlcd_init_display(struct charlcd *lcd)
 {
void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
@@ -254,7 +240,9 @@ static int charlcd_init_display(struct charlcd *lcd)
/* entry mode set : increment, cursor shifting */
hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
 
-   charlcd_clear_display(lcd);
+   lcd->ops->clear_display(lcd);
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
return 0;
 }
 
@@ -670,8 +658,10 @@ static int charlcd_open(struct inode *inode, struct file 
*file)
goto fail;
 
if (priv->must_clear) {
-   charlcd_clear_display(>lcd);
+   priv->lcd.ops->clear_display(>lcd);
priv->must_clear = false;
+   priv->lcd.addr.x = 0;
+   priv->lcd.addr.y = 0;
}
return nonseekable_open(inode, file);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 236fd0e9e8ab..a6c32c4d1aac 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -43,6 +43,9 @@ struct charlcd {
  * previously set in addr.x and addr.y by charlcd.
  * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
  * charlcd prior to calling this function.
+ * @clear_display: Again clear the whole display, set the cursor to 0, 0. The
+ * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
+ * function.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -50,6 +53,7 @@ struct charlcd_ops {
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
int (*home)(struct charlcd *lcd);
+   int (*clear_display)(struct charlcd *lcd);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index b0893ea49165..40ea6d25dbe1 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -129,6 +129,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
+   .clear_display  = hd44780_common_clear_display,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -175,6 +176,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
+   .clear_display  = hd44780_common_clear_display,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index ea62beada9d8..2f7d55668eb4 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -1,13 +1,22 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 #include 
+#include 
 #include 
 
 #include "charlcd.h"
 #include "hd44780_common.h"
 
 /* LCD commands */
+#define LCD_CMD_DISPLAY_CLEAR  0x01/* Clear entire display */
+
 #define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
 
+/* sleeps that many milliseconds with a reschedule */
+s

[PATCH v5 07/25] auxdisplay: Move addr out of charlcd_priv

2020-10-29 Thread poeschel
From: Lars Poeschel 

Move out the struct addr from struct charlcd_priv into the less private
struct charlcd. This member is used to pass position information. The
individual drivers need to be able to read this information, so we move
this out of charlcd_priv to charlcd structure.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 61 +++-
 drivers/auxdisplay/charlcd.h |  6 
 2 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index ce6622f71c34..1b37d4bc38f9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -72,12 +72,6 @@ struct charlcd_priv {
/* contains the LCD config state */
unsigned long int flags;
 
-   /* Contains the LCD X and Y offset */
-   struct {
-   unsigned long int x;
-   unsigned long int y;
-   } addr;
-
/* Current escape sequence and it's length or -1 if outside */
struct {
char buf[LCD_ESCAPE_LEN + 1];
@@ -148,7 +142,6 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
 
@@ -156,37 +149,34 @@ static void charlcd_gotoxy(struct charlcd *lcd)
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = priv->addr.x < hdc->bwidth ? priv->addr.x & (hdc->hwidth - 1)
+   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
  : hdc->bwidth - 1;
-   if (priv->addr.y & 1)
+   if (lcd->addr.y & 1)
addr += hdc->hwidth;
-   if (priv->addr.y & 2)
+   if (lcd->addr.y & 2)
addr += hdc->bwidth;
hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
-
-   priv->addr.x = 0;
-   priv->addr.y = 0;
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
charlcd_gotoxy(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
 
-   if (priv->addr.x < hdc->bwidth) {
+   if (lcd->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
hdc->write_data(hdc, c);
-   priv->addr.x++;
+   lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (priv->addr.x == hdc->bwidth)
+   if (lcd->addr.x == hdc->bwidth)
charlcd_gotoxy(lcd);
}
 }
@@ -210,12 +200,11 @@ static void charlcd_clear_fast(struct charlcd *lcd)
 /* clears the display and resets X/Y */
 static void charlcd_clear_display(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
 
hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   priv->addr.x = 0;
-   priv->addr.y = 0;
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
/* we must wait a few milliseconds (15) */
long_sleep(15);
 }
@@ -415,21 +404,21 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'l':   /* Shift Cursor Left */
-   if (priv->addr.x > 0) {
+   if (lcd->addr.x > 0) {
/* back one char if not at end of line */
-   if (priv->addr.x < hdc->bwidth)
+   if (lcd->addr.x < hdc->bwidth)
hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   priv->addr.x--;
+   lcd->addr.x--;
}
processed = 1;
break;
case 'r':   /* shift cursor right */
-   if (priv->addr.x < lcd->width) {
+   if (lcd->addr.x < lcd->width) {
/* allow the cursor to pass the end of the line */
-   if (priv->addr.x < (hdc->bwidth - 1))
+   if (lcd->addr.x < (hdc->bwidth - 1))
hdc->write_cmd(hdc,
LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
-   priv->addr.x++;
+   lcd->addr.x++;
}
processed = 1;
break;
@@ -446,7 +43

[PATCH v5 02/25] auxdisplay: Introduce hd44780_common.[ch]

2020-10-29 Thread poeschel
From: Lars Poeschel 

There is some hd44780 specific code in charlcd and this code is used by
multiple drivers. To make charlcd independent from this device specific
code this has to be moved to a place where the multiple drivers can
share their common code. This common place is now introduced as
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Remove some unnecessary newlines

Changes in v3:
- Fix some typos
---
 drivers/auxdisplay/Kconfig  | 20 ++
 drivers/auxdisplay/Makefile |  1 +
 drivers/auxdisplay/hd44780.c| 43 +++--
 drivers/auxdisplay/hd44780_common.c | 19 +
 drivers/auxdisplay/hd44780_common.h |  7 +
 drivers/auxdisplay/panel.c  | 18 ++--
 6 files changed, 91 insertions(+), 17 deletions(-)
 create mode 100644 drivers/auxdisplay/hd44780_common.c
 create mode 100644 drivers/auxdisplay/hd44780_common.h

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 81757eeded68..a56171d1a1ba 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -14,12 +14,31 @@ menuconfig AUXDISPLAY
 
  If you say N, all options in this submenu will be skipped and 
disabled.
 
+config CHARLCD
+   tristate "Character LCD core support" if COMPILE_TEST
+   help
+ This is the base system for character-based LCD displays.
+ It makes no sense to have this alone, you select your display driver
+ and if it needs the charlcd core, it will select it automatically.
+ This is some character LCD core interface that multiple drivers can
+ use.
+
+config HD44780_COMMON
+   tristate "Common functions for HD44780 (and compatibles) LCD displays" 
if COMPILE_TEST
+   help
+ This is a module with the common symbols for HD44780 (and compatibles)
+ displays. This is the code that multiple other modules use. It is not
+ useful alone. If you have some sort of HD44780 compatible display,
+ you very likely use this. It is selected automatically by selecting
+ your concrete display.
+
 if AUXDISPLAY
 
 config HD44780
tristate "HD44780 Character LCD support"
depends on GPIOLIB || COMPILE_TEST
select CHARLCD
+   select HD44780_COMMON
help
  Enable support for Character LCDs using a HD44780 controller.
  The LCD is accessible through the /dev/lcd char device (10, 156).
@@ -168,6 +187,7 @@ menuconfig PARPORT_PANEL
tristate "Parallel port LCD/Keypad Panel support"
depends on PARPORT
select CHARLCD
+   select HD44780_COMMON
help
  Say Y here if you have an HD44780 or KS-0074 LCD connected to your
  parallel port. This driver also features 4 and 6-key keypads. The LCD
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index cf54b5efb07e..7e8a8c3eb3c3 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_CHARLCD)  += charlcd.o
+obj-$(CONFIG_HD44780_COMMON)   += hd44780_common.o
 obj-$(CONFIG_ARM_CHARLCD)  += arm-charlcd.o
 obj-$(CONFIG_KS0108)   += ks0108.o
 obj-$(CONFIG_CFAG12864B)   += cfag12864b.o cfag12864bfb.o
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 5982158557bb..271dba9cd108 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -15,6 +15,7 @@
 #include 
 
 #include "charlcd.h"
+#include "hd44780_common.h"
 
 enum hd44780_pin {
/* Order does matter due to writing to GPIO array subsets! */
@@ -179,8 +180,9 @@ static int hd44780_probe(struct platform_device *pdev)
struct device *dev = >dev;
unsigned int i, base;
struct charlcd *lcd;
+   struct hd44780_common *hdc;
struct hd44780 *hd;
-   int ifwidth, ret;
+   int ifwidth, ret = -ENOMEM;
 
/* Required pins */
ifwidth = gpiod_count(dev, "data");
@@ -198,31 +200,39 @@ static int hd44780_probe(struct platform_device *pdev)
return -EINVAL;
}
 
+   hdc = hd44780_common_alloc();
+   if (!hdc)
+   return -ENOMEM;
+
lcd = charlcd_alloc(sizeof(struct hd44780));
if (!lcd)
-   return -ENOMEM;
+   goto fail1;
 
-   hd = lcd->drvdata;
+   hd = kzalloc(sizeof(struct hd44780), GFP_KERNEL);
+   if (!hd)
+   goto fail2;
 
+   hdc->hd44780 = hd;
+   lcd->drvdata = hdc;
for (i = 0; i < ifwidth; i++) {
hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i,
  GPIOD_OUT_LOW);
if (IS_ERR(hd->pins[base + i])) {
ret = PTR_ERR(hd->pins[base + i]);
-   

[PATCH 00/25] Make charlcd device independent

2020-10-29 Thread poeschel
From: Lars Poeschel 

This tries to make charlcd device independent. At the moment hd44780
device specific code is contained deep in charlcd. This moves this out
into a hd44780_common module, where the two hd44780 drivers we have at
the moment (hd44780 and panel) can use this from. The goal is that at
the end other drivers can use the charlcd interface.
I add one such driver for a modtronix lcd displau  with the last patch.
I submitted this already some time ago, where the wish was so split
this into smaller chunks what I try to do with this patchset.

This is v5 of the patchset. I address a few review comments with this.
I fixed some typos, but more importantly Miguel spotted that I reverted
commit 3f03b6498 ("auxdisplay: charlcd: Reuse hex_to_bin() instead of
custom code") during rebasing. This is corrected now.

As a note to patch 23:
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used so set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistens across different displays.
The new behaviour is to stop writing character at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependent anymore.

Link: https://lore.kernel.org/lkml/20191016082430.5955-1-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/CANiq72kS-u_Xd_m+2CQVh-JCncPf1XNXrXAZ=4z+mze8fwv...@mail.gmail.com/

Changes in v5:
- patch 1: Fix a commit message typo: of -> on
- patch 2: Remove some unnecessary newlines
- patch 8: Fix some typos
- patch 14: Fix commit message typo: it's -> its
- patch 15: this patch is squashed together from the former individual
  hd44780_common_ function patches
- patch 16: combined two cleanup patches
- patch 17: I did previously undo commit 3f03b6498 which was a mistake.
  This is now corrected.
- patch 24: Picked up Robs Reviewed-by
- patch 25: use hex_to_bin like in commit 3f03b6498 but for the lcd2s.c
  file

Changes in v4:
- modtronix -> Modtronix in new lcd2s driver
- Kconfig: remove "default n" in new lcd2s driver

Changes in v3:
- Fix some typos in Kconfig stuff
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
- new patch to reduce display timeout
- better patch description to why not move cursor beyond end of a line
- Fixed make dt_binding_doc errors

Changes in v2:
- split whole patch into many smaller chunks
- device tree doc in yaml

Lars Poeschel (25):
  auxdisplay: Use an enum for charlcd  backlight on/off ops
  auxdisplay: Introduce hd44780_common.[ch]
  auxdisplay: Move hwidth and bwidth to struct hd44780_common
  auxdisplay: Move ifwidth to struct hd44780_common
  auxdisplay: Move write_data pointer to hd44780_common
  auxdisplay: Move write_cmd pointers to hd44780 drivers
  auxdisplay: Move addr out of charlcd_priv
  auxdisplay: hd44780_common_print
  auxdisplay: provide hd44780_common_gotoxy
  auxdisplay: add home to charlcd_ops
  auxdisplay: Move clear_display to hd44780_common
  auxdisplay: make charlcd_backlight visible to hd44780_common
  auxdisplay: Make use of enum for backlight on / off
  auxdisplay: Move init_display to hd44780_common
  auxdisplay: implement various hd44780_common_ functions
  auxdisplay: cleanup unnecessary hd44780 code in charlcd
  auxdisplay: Move char redefine code to hd44780_common
  auxdisplay: Call charlcd_backlight in place
  auxdisplay: hd44780_common: Reduce clear_display timeout
  auxdisplay: hd44780: Remove clear_fast
  auxdisplay: charlcd: replace last device specific stuff
  auxdisplay: Change gotoxy calling interface
  auxdisplay: charlcd: Do not print chars at end of line
  auxdisplay: lcd2s DT binding doc
  auxdisplay: add a driver for lcd2s character display

 .../bindings/auxdisplay/modtronix,lcd2s.yaml  |  58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 drivers/auxdisplay/Kconfig|  30 ++
 drivers/auxdisplay/Makefile   |   2 +
 drivers/auxdisplay/charlcd.c  | 412 +-
 drivers/auxdisplay/charlcd.h  |  86 +++-
 drivers/auxdisplay/hd44780.c  | 120 +++--
 drivers/auxdisplay/hd44780_common.c   | 361 +++
 drivers/auxdisplay/hd44780_common.h   |  33 ++
 drivers/auxdisplay/lcd2s.c| 403 +
 drivers/auxdisplay/panel.c| 180 
 11 files changed, 1237 insertions(+), 450 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/auxdisplay/m

[PATCH v5 01/25] auxdisplay: Use an enum for charlcd backlight on/off ops

2020-10-29 Thread poeschel
From: Lars Poeschel 

We use an enum for calling the functions in charlcd, that turn the
backlight on or off. This enum is generic and can be used for other
charlcd turn on / turn off operations as well.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v5:
- Fix a commit message typo: of -> on
---
 drivers/auxdisplay/charlcd.c | 2 +-
 drivers/auxdisplay/charlcd.h | 7 ++-
 drivers/auxdisplay/hd44780.c | 2 +-
 drivers/auxdisplay/panel.c   | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 5aee0f546351..8aaee0fea9ab 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -101,7 +101,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, int on)
+static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 00911ad0f3de..c66f038e5d2b 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -9,6 +9,11 @@
 #ifndef _CHARLCD_H
 #define _CHARLCD_H
 
+enum charlcd_onoff {
+   CHARLCD_OFF = 0,
+   CHARLCD_ON,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -30,7 +35,7 @@ struct charlcd_ops {
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
void (*clear_fast)(struct charlcd *lcd);
-   void (*backlight)(struct charlcd *lcd, int on);
+   void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 struct charlcd *charlcd_alloc(unsigned int drvdata_size);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index bcbe13092327..5982158557bb 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -37,7 +37,7 @@ struct hd44780 {
struct gpio_desc *pins[PIN_NUM];
 };
 
-static void hd44780_backlight(struct charlcd *lcd, int on)
+static void hd44780_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct hd44780 *hd = lcd->drvdata;
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 1c82d824ae00..de623ae219f1 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -708,7 +708,7 @@ static void lcd_send_serial(int byte)
 }
 
 /* turn the backlight on or off */
-static void lcd_backlight(struct charlcd *charlcd, int on)
+static void lcd_backlight(struct charlcd *charlcd, enum charlcd_onoff on)
 {
if (lcd.pins.bl == PIN_NONE)
return;
-- 
2.28.0



Re: [PATCH v4 00/32] Make charlcd device independent

2020-10-22 Thread Lars Poeschel
On Fri, Oct 16, 2020 at 05:59:04AM +0200, Miguel Ojeda wrote:
> On Fri, Oct 16, 2020 at 4:33 AM Miguel Ojeda
>  wrote:
> >
> > Picking these for linux-next (including Rob's Reviewed-by). I have
> > spotted a few typos that I corrected -- I will note them by email.
> 
> Hmm, I think we should do another round instead, since I found what
> looks to be an unintended revert of a previous commit in patch 24.
> Lars, can you please take a look?

I will work on this soon.

> Also, please take the chance to apply my comments given we have a new
> round (and Rob's Reviewed-by too).

Yes, of course.

> By the way, I think you could simplify by squashing the "implement
> hd44780_*" commits together (i.e. from 15 to 22 except 20), and the
> two cleanups together too (i.e. 20 and 23). I know we asked you to
> split things up before, but those two sets are quite similar
> (including in their commit message) and easy to understand all
> together.

No problem. I will do this as well.

Regards,
Lars


Re: [PATCH v4 00/32] Make charlcd device independent

2020-10-06 Thread Lars Poeschel
On Mon, Oct 05, 2020 at 05:30:59PM +0200, Miguel Ojeda wrote:
> Hi Lars,
> 
> On Mon, Oct 5, 2020 at 2:27 PM  wrote:
> >
> > This tries to make charlcd device independent.
> 
> Thanks a lot for the work!
> 
> I see you have written the differences between versions in each patch,
> but given there are 32 patches, it'd be nice to comment which ones have
> changed so that folks that already did a review can take a look at
> those.

Changes in v4:
- modtronix -> Modtronix in new lcd2s driver
- Kconfig: remove "default n" in new lcd2s driver

Changes in v3:
- Fix some typos in Kconfig stuff
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
- new patch to reduce display timeout
- better patch description to why not move cursor beyond end of a line
- Fixed make dt_binding_doc errors

Changes in v2:
- split whole patch into many smaller chunks
- device tree doc in yaml

Regards,
Lars


Re: [PATCH 1/2] pwm: sysfs: Set class on pwm devices

2020-10-05 Thread Lars Poeschel
On Fri, Oct 02, 2020 at 03:35:12PM +0200, Greg Kroah-Hartman wrote:
> On Fri, Oct 02, 2020 at 03:08:44PM +0200, Lars Poeschel wrote:
> > On Fri, Oct 02, 2020 at 02:46:16PM +0200, Greg Kroah-Hartman wrote:
> > > On Fri, Oct 02, 2020 at 02:30:47PM +0200, poesc...@lemonage.de wrote:
> > > > From: Lars Poeschel 
> > > > 
> > > > This adds a class to exported pwm devices.
> > > > Exporting a pwm through sysfs did not yield udev events. The
> > > > dev_uevent_filter function does filter-out devices without a bus or
> > > > class.
> > > > This was already addressed in commit
> > > > commit 7e5d1fd75c3d ("pwm: Set class for exported channels in sysfs")
> > > > but this did cause problems and the commit got reverted with
> > > > commit c289d6625237 ("Revert "pwm: Set class for exported channels in
> > > > sysfs"")
> > > > Problem with the previous approach was, that there is a clash if we have
> > > > multiple pwmchips:
> > > > echo 0 > pwmchip0/export
> > > > echo 0 > pwmchip1/export
> > > > would both export /sys/class/pwm/pwm0 .
> > > > 
> > > > Now this patch changes the sysfs interface. We do include the pwmchip
> > > > number into the pwm directory that gets exported.
> > > > With the example above we get:
> > > > /sys/class/pwm/pwm-0-0
> > > > /sys/class/pwm/pwm-1-0
> > > > We maintain ABI backward compatibility through symlinks.
> > > > /sys/class/pwm/pwmchip0/pwm0
> > > > /sys/class/pwm/pwmchip1/pwm0
> > > > are now symbolic links to the new names.
> > > > 
> > > > Cc: Greg Kroah-Hartman 
> > > > Signed-off-by: Lars Poeschel 
> > > > ---
> > > >  drivers/pwm/sysfs.c | 57 +
> > > >  1 file changed, 47 insertions(+), 10 deletions(-)
> > > > 
> > > > diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
> > > > index 449dbc0f49ed..c708da17a857 100644
> > > > --- a/drivers/pwm/sysfs.c
> > > > +++ b/drivers/pwm/sysfs.c
> > > > @@ -240,8 +240,10 @@ static void pwm_export_release(struct device 
> > > > *child)
> > > >  
> > > >  static int pwm_export_child(struct device *parent, struct pwm_device 
> > > > *pwm)
> > > >  {
> > > > +   struct pwm_chip *chip = dev_get_drvdata(parent);
> > > > struct pwm_export *export;
> > > > char *pwm_prop[2];
> > > > +   char *link_name;
> > > > int ret;
> > > >  
> > > > if (test_and_set_bit(PWMF_EXPORTED, >flags))
> > > > @@ -256,25 +258,39 @@ static int pwm_export_child(struct device 
> > > > *parent, struct pwm_device *pwm)
> > > > export->pwm = pwm;
> > > > mutex_init(>lock);
> > > >  
> > > > +   export->child.class = parent->class;
> > > > export->child.release = pwm_export_release;
> > > > export->child.parent = parent;
> > > > export->child.devt = MKDEV(0, 0);
> > > > export->child.groups = pwm_groups;
> > > > -   dev_set_name(>child, "pwm%u", pwm->hwpwm);
> > > > +   dev_set_name(>child, "pwm-%u-%u", chip->base, 
> > > > pwm->hwpwm);
> > > >  
> > > > ret = device_register(>child);
> > > > -   if (ret) {
> > > > -   clear_bit(PWMF_EXPORTED, >flags);
> > > > -   put_device(>child);
> > > > -   export = NULL;
> > > > -   return ret;
> > > > +   if (ret)
> > > > +   goto error;
> > > > +
> > > > +   link_name = kasprintf(GFP_KERNEL, "pwm%u", pwm->hwpwm);
> > > > +   if (link_name == NULL) {
> > > > +   ret = -ENOMEM;
> > > > +   goto dev_unregister;
> > > > }
> > > > -   pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=pwm%u", pwm->hwpwm);
> > > > +
> > > > +   pwm_prop[0] = kasprintf(GFP_KERNEL, "EXPORT=%s",
> > > > +   export->child.kobj.name);
> > > > pwm_prop[1] = NULL;
> > > >  

[PATCH v4 15/32] auxdisplay: implement hd44780_common_shift_cursor

2020-10-05 Thread poeschel
From: Lars Poeschel 

Implement a hd44780_common_shift_cursor function for drivers to use and
make charlcd use this function through ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 33 -
 drivers/auxdisplay/charlcd.h|  7 ++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 22 +++
 drivers/auxdisplay/hd44780_common.h |  2 ++
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 94f6b0afab13..85747e13bf48 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -288,21 +288,18 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'l':   /* Shift Cursor Left */
if (lcd->addr.x > 0) {
-   /* back one char if not at end of line */
-   if (lcd->addr.x < hdc->bwidth)
-   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   lcd->addr.x--;
+   if (!lcd->ops->shift_cursor(lcd, CHARLCD_SHIFT_LEFT))
+   lcd->addr.x--;
}
+
processed = 1;
break;
case 'r':   /* shift cursor right */
if (lcd->addr.x < lcd->width) {
-   /* allow the cursor to pass the end of the line */
-   if (lcd->addr.x < (hdc->bwidth - 1))
-   hdc->write_cmd(hdc,
-   LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
-   lcd->addr.x++;
+   if (!lcd->ops->shift_cursor(lcd, CHARLCD_SHIFT_RIGHT))
+   lcd->addr.x++;
}
+
processed = 1;
break;
case 'L':   /* shift display left */
@@ -456,19 +453,17 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
case '\b':
/* go back one char and clear it */
if (lcd->addr.x > 0) {
-   /*
-* check if we're not at the
-* end of the line
-*/
-   if (lcd->addr.x < hdc->bwidth)
-   /* back one char */
-   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   lcd->addr.x--;
+   /* back one char */
+   if (!lcd->ops->shift_cursor(lcd,
+   CHARLCD_SHIFT_LEFT))
+   lcd->addr.x--;
}
/* replace with a space */
-   hdc->write_data(hdc, ' ');
+   charlcd_print(lcd, ' ');
/* back one char again */
-   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
+   if (!lcd->ops->shift_cursor(lcd, CHARLCD_SHIFT_LEFT))
+   lcd->addr.x--;
+
break;
case '\f':
/* quickly clear the display */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 6281cf299a6d..0a340beacd3e 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -21,6 +21,11 @@ enum charlcd_onoff {
CHARLCD_ON,
 };
 
+enum charlcd_shift_dir {
+   CHARLCD_SHIFT_LEFT,
+   CHARLCD_SHIFT_RIGHT,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -53,6 +58,7 @@ struct charlcd {
  * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
  * function.
  * @init_display: Initialize the display.
+ * @shift_cursor: Shift cursor left or right one position.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -62,6 +68,7 @@ struct charlcd_ops {
int (*home)(struct charlcd *lcd);
int (*clear_display)(struct charlcd *lcd);
int (*init_display)(struct charlcd *lcd);
+   int (*shift_cursor)(struct charlcd *lcd, enum charlcd_shift_dir dir);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 5916da09f738..6ffeeb3fb0d0 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -131,6 +131,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.home   = hd44780_common_home,
 

[PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off

2020-10-05 Thread poeschel
From: Lars Poeschel 

To turn the backlight on or off use our new enum CHARLCD_ON /
CHARLCD_OFF.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 154419513186..9631f70e8128 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -115,7 +115,7 @@ static void charlcd_bl_off(struct work_struct *work)
if (priv->bl_tempo) {
priv->bl_tempo = false;
if (!(priv->flags & LCD_FLAG_L))
-   priv->lcd.ops->backlight(>lcd, 0);
+   priv->lcd.ops->backlight(>lcd, CHARLCD_OFF);
}
mutex_unlock(>bl_tempo_lock);
 }
@@ -132,7 +132,7 @@ void charlcd_poke(struct charlcd *lcd)
 
mutex_lock(>bl_tempo_lock);
if (!priv->bl_tempo && !(priv->flags & LCD_FLAG_L))
-   lcd->ops->backlight(lcd, 1);
+   lcd->ops->backlight(lcd, CHARLCD_ON);
priv->bl_tempo = true;
schedule_delayed_work(>bl_work, LCD_BL_TEMPO_PERIOD * HZ);
mutex_unlock(>bl_tempo_lock);
@@ -829,7 +829,7 @@ int charlcd_unregister(struct charlcd *lcd)
the_charlcd = NULL;
if (lcd->ops->backlight) {
cancel_delayed_work_sync(>bl_work);
-   priv->lcd.ops->backlight(>lcd, 0);
+   priv->lcd.ops->backlight(>lcd, CHARLCD_OFF);
}
 
return 0;
-- 
2.28.0



[PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

Take the code to redefine characters out of charlcd and move it to
hd44780_common, as this is hd44780 specific.
There is now a function hd44780_common_redefine_char that drivers use
and charlcd calls it through its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 60 +++
 drivers/auxdisplay/charlcd.h|  2 +
 drivers/auxdisplay/hd44780.c|  2 +
 drivers/auxdisplay/hd44780_common.c | 63 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 ++
 6 files changed, 76 insertions(+), 55 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 29737c3e18f6..dca1b138a239 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -25,8 +25,6 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-#define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
-
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
 
@@ -344,61 +342,13 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
LCD_FLAG_C | LCD_FLAG_B;
processed = 1;
break;
-   case 'G': {
-   /* Generator : LGcx...xx; must have  between '0'
-* and '7', representing the numerical ASCII code of the
-* redefined character, and  a sequence of 16
-* hex digits representing 8 bytes for each character.
-* Most LCDs will only use 5 lower bits of the 7 first
-* bytes.
-*/
-
-   unsigned char cgbytes[8];
-   unsigned char cgaddr;
-   int cgoffset;
-   int shift;
-   char value;
-   int addr;
-
-   if (!strchr(esc, ';'))
-   break;
-
-   esc++;
-
-   cgaddr = *(esc++) - '0';
-   if (cgaddr > 7) {
+   case 'G':
+   if (lcd->ops->redefine_char)
+   processed = lcd->ops->redefine_char(lcd, esc);
+   else
processed = 1;
-   break;
-   }
-
-   cgoffset = 0;
-   shift = 0;
-   value = 0;
-   while (*esc && cgoffset < 8) {
-   int half;
-
-   shift ^= 4;
-
-   half = hex_to_bin(*esc++);
-   if (half < 0)
-   continue;
-
-   value |= half << shift;
-   if (shift == 0) {
-   cgbytes[cgoffset++] = value;
-   value = 0;
-   }
-   }
-
-   hdc->write_cmd(hdc, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
-   for (addr = 0; addr < cgoffset; addr++)
-   hdc->write_data(hdc, cgbytes[addr]);
-
-   /* ensures that we stop writing to CGRAM */
-   lcd->ops->gotoxy(lcd);
-   processed = 1;
break;
-   }
+
case 'x':   /* gotoxy : LxXXX[yYYY]; */
case 'y':   /* gotoxy : LyYYY[xXXX]; */
if (priv->esc_seq.buf[priv->esc_seq.len - 1] != ';')
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5b0717c7482b..83fa989d37fa 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -74,6 +74,7 @@ struct charlcd {
  * @cursor: Turn cursor on or off.
  * @blink: Turn cursor blink on or off.
  * @lines: One or two lines.
+ * @redefine_char: Redefine the actual pixel matrix of character.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -90,6 +91,7 @@ struct charlcd_ops {
int (*blink)(struct charlcd *lcd, enum charlcd_onoff on);
int (*fontsize)(struct charlcd *lcd, enum charlcd_fontsize size);
int (*lines)(struct charlcd *lcd, enum charlcd_lines lines);
+   int (*redefine_char)(struct charlcd *lcd, char *esc);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 7b7b28d72198..2e5e7c993933 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -138,6 +138,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.blink  = hd44780_common_blink,
.fontsize   = hd44780_common_fontsize,
.lines  = hd44780_common_lines,
+   .redefine_char  = hd44780_common_redefine_char,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mod

[PATCH v4 26/32] auxdisplay: hd44780_common: Reduce clear_display timeout

2020-10-05 Thread poeschel
From: Lars Poeschel 

Digging in the hd44780 datasheet revealed that the timeout needed after
clearing the whole display is only 1,64ms not 15ms. So we can reduce
that timeout.

Link: https://lore.kernel.org/lkml/20200922092121.gg16...@1wt.eu/
Link: https://www.crystalfontz.com/controllers/Hitachi/HD44780/433/

Signed-off-by: Lars Poeschel 
---
Changes in v3:
- This patch is new in v3
---
 drivers/auxdisplay/hd44780_common.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 82afae78f46e..fbce8835a650 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -83,8 +83,8 @@ int hd44780_common_clear_display(struct charlcd *lcd)
struct hd44780_common *hdc = lcd->drvdata;
 
hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   /* we must wait a few milliseconds (15) */
-   long_sleep(15);
+   /* datasheet says to wait 1,64 milliseconds */
+   long_sleep(2);
return 0;
 }
 EXPORT_SYMBOL_GPL(hd44780_common_clear_display);
-- 
2.28.0



[PATCH v4 30/32] auxdisplay: charlcd: Do not print chars at end of line

2020-10-05 Thread poeschel
From: Lars Poeschel 

Skip printing characters at the end of a display line. This fits to the
behaviour we already had, that the cursor is nailed to last position of
a line.
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used so set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistens across different displays.
The new behaviour is to stop writing character at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependents anymore.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v3:
- Better patch description
---
 drivers/auxdisplay/charlcd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index ef10b5ca0e16..f43430e9dcee 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -111,6 +111,9 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
+   if (lcd->addr.x >= lcd->width)
+   return;
+
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
-- 
2.28.0



[PATCH v4 28/32] auxdisplay: charlcd: replace last device specific stuff

2020-10-05 Thread poeschel
From: Lars Poeschel 

These are the last bits left in charlcd.c that are device specific and
they are removed now.
In detail this is:
* bwidth, which is the width of the display buffer per line. This is
  replaced by width of the display.
* hwidth, which is the size of the display buffer as a whole. This is
  replaced by looping all chars of a line by all lines.
* the hd44780_common header include can go away.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 077c01e87127..59f21401d6a9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -20,7 +20,6 @@
 #include 
 
 #include "charlcd.h"
-#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
@@ -112,8 +111,6 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
-
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
@@ -121,7 +118,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == hdc->bwidth)
+   if (lcd->addr.x == lcd->width)
lcd->ops->gotoxy(lcd);
 }
 
@@ -195,7 +192,6 @@ static bool parse_xy(const char *s, unsigned long *x, 
unsigned long *y)
 static inline int handle_lcd_special_code(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
 
/* LCD special codes */
 
@@ -323,7 +319,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
xs = lcd->addr.x;
ys = lcd->addr.y;
-   for (x = lcd->addr.x; x < hdc->bwidth; x++)
+   for (x = lcd->addr.x; x < lcd->width; x++)
lcd->ops->print(lcd, ' ');
 
/* restore cursor position */
@@ -366,7 +362,6 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 static void charlcd_write_char(struct charlcd *lcd, char c)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
 
/* first, we'll test if we're in escape mode */
if ((c != '\n') && priv->esc_seq.len >= 0) {
@@ -407,7 +402,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * flush the remainder of the current line and
 * go to the beginning of the next line
 */
-   for (; lcd->addr.x < hdc->bwidth; lcd->addr.x++)
+   for (; lcd->addr.x < lcd->width; lcd->addr.x++)
lcd->ops->print(lcd, ' ');
 
lcd->addr.x = 0;
-- 
2.28.0



[PATCH v4 18/32] auxdisplay: Implement hd44780_common_cursor

2020-10-05 Thread poeschel
From: Lars Poeschel 

Implement a hd44780_common_cursor function to turn the cursor on and
off. The hd44780 drivers can use this function and charlcd calls it
through its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c|  6 ++
 drivers/auxdisplay/charlcd.h|  2 ++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 14 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 28 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 9bd3c0f2c470..a2f0becb1a9f 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -246,10 +246,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'C':   /* Cursor ON */
priv->flags |= LCD_FLAG_C;
+   if (priv->flags != oldflags)
+   lcd->ops->cursor(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'c':   /* Cursor OFF */
priv->flags &= ~LCD_FLAG_C;
+   if (priv->flags != oldflags)
+   lcd->ops->cursor(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case 'B':   /* Blink ON */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index ec739a25195e..5aab359ebd91 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -61,6 +61,7 @@ struct charlcd {
  * @shift_cursor: Shift cursor left or right one position.
  * @shift_display: Shift whole display content left or right.
  * @display: Turn display on or off.
+ * @cursor: Turn cursor on or off.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -73,6 +74,7 @@ struct charlcd_ops {
int (*shift_cursor)(struct charlcd *lcd, enum charlcd_shift_dir dir);
int (*shift_display)(struct charlcd *lcd, enum charlcd_shift_dir dir);
int (*display)(struct charlcd *lcd, enum charlcd_onoff on);
+   int (*cursor)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 0f76b812fa20..d5ce3955b577 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -134,6 +134,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.shift_cursor   = hd44780_common_shift_cursor,
.shift_display  = hd44780_common_shift_display,
.display= hd44780_common_display,
+   .cursor = hd44780_common_cursor,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -185,6 +186,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.shift_cursor   = hd44780_common_shift_cursor,
.shift_display  = hd44780_common_shift_display,
.display= hd44780_common_display,
+   .cursor = hd44780_common_cursor,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 07fd03555e99..587385e55bae 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -222,6 +222,20 @@ int hd44780_common_display(struct charlcd *lcd, enum 
charlcd_onoff on)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_display);
 
+int hd44780_common_cursor(struct charlcd *lcd, enum charlcd_onoff on)
+{
+   struct hd44780_common *hdc = lcd->drvdata;
+
+   if (on == CHARLCD_ON)
+   hdc->hd44780_common_flags |= LCD_FLAG_C;
+   else
+   hdc->hd44780_common_flags &= ~LCD_FLAG_C;
+
+   hd44780_common_set_mode(hdc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_cursor);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 1550fa77b956..7327a9b2e997 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -25,5 +25,6 @@ int hd44780_common_shift_cursor(struct charlcd *lcd,
 int hd44780_common_shift_display(struct charlcd *lcd,
enum charlcd_shift_dir dir);
 int hd44780_common_display(struct charlcd *lcd, enum charlcd_onoff on);
+int hd44780_common_cursor(struct charlcd *lcd, enum charlcd_onoff on);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 9cb895c74cfb..26fbf91c1501 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -882,6 +882,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
.shift_cursor   = hd44780_common_shift_cursor,
.shift_display  = hd44780_common_shift_display,
   

[PATCH v4 27/32] auxdisplay: hd44780: Remove clear_fast

2020-10-05 Thread poeschel
From: Lars Poeschel 

We remove the hd44780_clear_fast (display) clear implementation. With
the new timeout the normal clear_display is reasonably fast. So there is
no need for a clear_fast anymore.

Link: https://lore.kernel.org/lkml/20200922092121.gg16...@1wt.eu/

Signed-off-by: Lars Poeschel 
---
Changes in v3:
- This patch is squashed together from 26, 27 and 28 from previous patch
  set:
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-27-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-28-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/20200921144645.2061313-29-poesc...@lemonage.de/

- Additionally this now removes clear_fast from charlcd_ops and from
  panel driver.

---
 drivers/auxdisplay/charlcd.c | 21 ---
 drivers/auxdisplay/charlcd.h |  6 ++--
 drivers/auxdisplay/panel.c   | 67 
 3 files changed, 8 insertions(+), 86 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 0f0568a4bd35..077c01e87127 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -125,20 +125,11 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->ops->gotoxy(lcd);
 }
 
-static void charlcd_clear_fast(struct charlcd *lcd)
+static void charlcd_clear_display(struct charlcd *lcd)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
-   int pos;
-
-   charlcd_home(lcd);
-
-   if (lcd->ops->clear_fast)
-   lcd->ops->clear_fast(lcd);
-   else
-   for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   lcd->ops->print(lcd, ' ');
-
-   charlcd_home(lcd);
+   lcd->ops->clear_display(lcd);
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
 }
 
 /*
@@ -409,7 +400,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
break;
case '\f':
/* quickly clear the display */
-   charlcd_clear_fast(lcd);
+   charlcd_clear_display(lcd);
break;
case '\n':
/*
@@ -448,7 +439,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 
if (!strcmp(priv->esc_seq.buf, "[2J")) {
/* clear the display */
-   charlcd_clear_fast(lcd);
+   charlcd_clear_display(lcd);
processed = 1;
} else if (!strcmp(priv->esc_seq.buf, "[H")) {
/* cursor to home */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 83fa989d37fa..024f7188b5cc 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -55,7 +55,6 @@ struct charlcd {
 /**
  * struct charlcd_ops - Functions used by charlcd. Drivers have to implement
  * these.
- * @clear_fast: Clear the whole display and set cursor to position 0, 0.
  * @backlight: Turn backlight on or off. Optional.
  * @print: just Print one character to the display at current cursor position.
  * The buffered cursor position is advanced by charlcd. The cursor should not
@@ -64,8 +63,8 @@ struct charlcd {
  * previously set in addr.x and addr.y by charlcd.
  * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
  * charlcd prior to calling this function.
- * @clear_display: Again clear the whole display, set the cursor to 0, 0. The
- * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
+ * @clear_display: Clear the whole display and set the cursor to 0, 0. The
+ * values in addr.x and addr.y are set to 0, 0 by charlcd after to calling this
  * function.
  * @init_display: Initialize the display.
  * @shift_cursor: Shift cursor left or right one position.
@@ -77,7 +76,6 @@ struct charlcd {
  * @redefine_char: Redefine the actual pixel matrix of character.
  */
 struct charlcd_ops {
-   void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index b0d2ae5b9be8..e07fadac281d 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -808,72 +808,7 @@ static void lcd_write_data_tilcd(struct hd44780_common 
*hdc, int data)
spin_unlock_irq(_lock);
 }
 
-/* fills the display with spaces and resets X/Y */
-static void lcd_clear_fast_s(struct charlcd *charlcd)
-{
-   struct hd44780_common *hdc = charlcd->drvdata;
-   int pos;
-
-   spin_lock_irq(_lock);
-   for (pos = 0; pos < charlcd->height * hdc->hwidth; pos++) {
-   lcd_send_serial(0x5F);  /* R/W=W, RS=1 */
-   lcd_send_serial(' ' & 0x0F);
-   

[PATCH v4 25/32] auxdisplay: Call charlcd_backlight in place

2020-10-05 Thread poeschel
From: Lars Poeschel 

This moves the call to charlcd_backlight from the end of the switch
into the actual case statement that originates the change of the
backlight. This is more consistent to what is now found in this switch.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index dca1b138a239..0f0568a4bd35 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -259,10 +259,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case '+':   /* Back light ON */
priv->flags |= LCD_FLAG_L;
+   if (priv->flags != oldflags)
+   charlcd_backlight(lcd, CHARLCD_ON);
+
processed = 1;
break;
case '-':   /* Back light OFF */
priv->flags &= ~LCD_FLAG_L;
+   if (priv->flags != oldflags)
+   charlcd_backlight(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case '*':   /* Flash back light */
@@ -363,14 +369,6 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
}
 
-   /* TODO: This indent party here got ugly, clean it! */
-   /* Check whether one flag was changed */
-   if (oldflags == priv->flags)
-   return processed;
-
-   if ((oldflags ^ priv->flags) & LCD_FLAG_L)
-   charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
-
return processed;
 }
 
-- 
2.28.0



[PATCH v4 23/32] auxdisplay: Remove unnecessary hd44780 from charlcd

2020-10-05 Thread poeschel
From: Lars Poeschel 

The last two commits made another chunk of hd44780 code unnecessary
which we remove here.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 17 +
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index d672e4c371e1..29737c3e18f6 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -25,16 +25,8 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-/* LCD commands */
-#define LCD_CMD_FUNCTION_SET   0x20/* Set function */
-#define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
-#define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
-#define LCD_CMD_FONT_5X10_DOTS 0x04/* Set char font to 5x10 dots */
-
 #define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
 
-#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
-
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
 
@@ -426,14 +418,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (oldflags == priv->flags)
return processed;
 
-   if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
-   hdc->write_cmd(hdc,
-   LCD_CMD_FUNCTION_SET |
-   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-   ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 
0) |
-   ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
-   /* check whether L flag was changed */
-   else if ((oldflags ^ priv->flags) & LCD_FLAG_L)
+   if ((oldflags ^ priv->flags) & LCD_FLAG_L)
charlcd_backlight(lcd, !!(priv->flags & LCD_FLAG_L));
 
return processed;
-- 
2.28.0



[PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display

2020-10-05 Thread poeschel
From: Lars Poeschel 

This driver allows to use a lcd2s 20x4 character display from Modtronix
engineering as an auxdisplay charlcd device.

Signed-off-by: Lars Poeschel 
---
Changes in v4:
- modtronix -> Modtronix
- Kconfig: remove "default n"

---
 drivers/auxdisplay/Kconfig  |  10 +
 drivers/auxdisplay/Makefile |   1 +
 drivers/auxdisplay/lcd2s.c  | 409 
 3 files changed, 420 insertions(+)
 create mode 100644 drivers/auxdisplay/lcd2s.c

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index a56171d1a1ba..96c8cdfce48d 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -173,6 +173,16 @@ config HT16K33
  Say yes here to add support for Holtek HT16K33, RAM mapping 16*8
  LED controller driver with keyscan.
 
+config LCD2S
+   tristate "lcd2s 20x4 character display over I2C console"
+   depends on I2C
+   select CHARLCD
+   help
+ This is a driver that lets you use the lcd2s 20x4 character display
+ from Modtronix engineering as a console output device. The display
+ is a simple single color character display. You have to connect it
+ to an I2C bus.
+
 config ARM_CHARLCD
bool "ARM Ltd. Character LCD Driver"
depends on PLAT_VERSATILE
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index 7e8a8c3eb3c3..307771027c89 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_IMG_ASCII_LCD)   += img-ascii-lcd.o
 obj-$(CONFIG_HD44780)  += hd44780.o
 obj-$(CONFIG_HT16K33)  += ht16k33.o
 obj-$(CONFIG_PARPORT_PANEL)+= panel.o
+obj-$(CONFIG_LCD2S)+= lcd2s.o
diff --git a/drivers/auxdisplay/lcd2s.c b/drivers/auxdisplay/lcd2s.c
new file mode 100644
index ..4b8c597a26fa
--- /dev/null
+++ b/drivers/auxdisplay/lcd2s.c
@@ -0,0 +1,409 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  console driver for LCD2S 4x20 character displays connected through i2c.
+ *  The display also has a spi interface, but the driver does not support
+ *  this yet.
+ *
+ *  This is a driver allowing you to use a LCD2S 4x20 from modtronix
+ *  engineering as auxdisplay character device.
+ *
+ *  (C) 2019 by Lemonage Software GmbH
+ *  Author: Lars Pöschel 
+ *  All rights reserved.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "charlcd.h"
+
+#define LCD2S_CMD_CUR_MOVES_FWD0x09
+#define LCD2S_CMD_CUR_BLINK_OFF0x10
+#define LCD2S_CMD_CUR_UL_OFF   0x11
+#define LCD2S_CMD_DISPLAY_OFF  0x12
+#define LCD2S_CMD_CUR_BLINK_ON 0x18
+#define LCD2S_CMD_CUR_UL_ON0x19
+#define LCD2S_CMD_DISPLAY_ON   0x1a
+#define LCD2S_CMD_BACKLIGHT_OFF0x20
+#define LCD2S_CMD_BACKLIGHT_ON 0x28
+#define LCD2S_CMD_WRITE0x80
+#define LCD2S_CMD_MOV_CUR_RIGHT0x83
+#define LCD2S_CMD_MOV_CUR_LEFT 0x84
+#define LCD2S_CMD_SHIFT_RIGHT  0x85
+#define LCD2S_CMD_SHIFT_LEFT   0x86
+#define LCD2S_CMD_SHIFT_UP 0x87
+#define LCD2S_CMD_SHIFT_DOWN   0x88
+#define LCD2S_CMD_CUR_ADDR 0x89
+#define LCD2S_CMD_CUR_POS  0x8a
+#define LCD2S_CMD_CUR_RESET0x8b
+#define LCD2S_CMD_CLEAR0x8c
+#define LCD2S_CMD_DEF_CUSTOM_CHAR  0x92
+#define LCD2S_CMD_READ_STATUS  0xd0
+
+#define LCD2S_CHARACTER_SIZE   8
+
+#define LCD2S_STATUS_BUF_MASK  0x7f
+
+struct lcd2s_data {
+   struct i2c_client *i2c;
+   struct charlcd *charlcd;
+};
+
+static s32 lcd2s_wait_buf_free(const struct i2c_client *client, int count)
+{
+   s32 status;
+
+   status = i2c_smbus_read_byte_data(client, LCD2S_CMD_READ_STATUS);
+   if (status < 0)
+   return status;
+
+   while ((status & LCD2S_STATUS_BUF_MASK) < count) {
+   mdelay(1);
+   status = i2c_smbus_read_byte_data(client,
+ LCD2S_CMD_READ_STATUS);
+   if (status < 0)
+   return status;
+   }
+   return 0;
+}
+
+static int lcd2s_i2c_master_send(const struct i2c_client *client,
+const char *buf, int count)
+{
+   s32 status;
+
+   status = lcd2s_wait_buf_free(client, count);
+   if (status < 0)
+   return status;
+
+   return i2c_master_send(client, buf, count);
+}
+
+static int lcd2s_i2c_smbus_write_byte(const struct i2c_client *client, u8 
value)
+{
+   s32 status;
+
+   status = lcd2s_wait_buf_free(client, 1);
+   if (status < 0)
+   return status;
+
+   return i2c_smbus_write_byte(client, value);
+}
+
+static int lcd2s_print(struct charlcd *lcd, int c)
+{
+   struct lcd2s_data *lcd2s = lcd->drvdata;
+   u8 buf[2] = { LCD2

[PATCH v4 29/32] auxdisplay: Change gotoxy calling interface

2020-10-05 Thread poeschel
From: Lars Poeschel 

Change the calling interface for gotoxy from supplying the x and y
coordinates in the charlcd struct to explicitly supplying x and y in
the function arguments. This is more intuitive and allows for moving
the cursor to positions independent from the position saved in the
charlcd struct.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 10 +-
 drivers/auxdisplay/charlcd.h|  2 +-
 drivers/auxdisplay/hd44780_common.c | 15 ++-
 drivers/auxdisplay/hd44780_common.h |  2 +-
 4 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 59f21401d6a9..ef10b5ca0e16 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -119,7 +119,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
 
/* prevents the cursor from wrapping onto the next line */
if (lcd->addr.x == lcd->width)
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x - 1, lcd->addr.y);
 }
 
 static void charlcd_clear_display(struct charlcd *lcd)
@@ -325,7 +325,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
/* restore cursor position */
lcd->addr.x = xs;
lcd->addr.y = ys;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
processed = 1;
break;
}
@@ -349,7 +349,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
/* If the command is valid, move to the new address */
if (parse_xy(esc, >addr.x, >addr.y))
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
 
/* Regardless of its validity, mark as processed */
processed = 1;
@@ -407,12 +407,12 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
 
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
break;
case '\r':
/* go to the beginning of the same line */
lcd->addr.x = 0;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
break;
case '\t':
/* print a space instead of the tab */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 024f7188b5cc..26f4ad178852 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -78,7 +78,7 @@ struct charlcd {
 struct charlcd_ops {
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
-   int (*gotoxy)(struct charlcd *lcd);
+   int (*gotoxy)(struct charlcd *lcd, unsigned int x, unsigned int y);
int (*home)(struct charlcd *lcd);
int (*clear_display)(struct charlcd *lcd);
int (*init_display)(struct charlcd *lcd);
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index fbce8835a650..b949bbd8063a 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -49,7 +49,7 @@ int hd44780_common_print(struct charlcd *lcd, int c)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_print);
 
-int hd44780_common_gotoxy(struct charlcd *lcd)
+int hd44780_common_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y)
 {
struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
@@ -58,11 +58,10 @@ int hd44780_common_gotoxy(struct charlcd *lcd)
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
- : hdc->bwidth - 1;
-   if (lcd->addr.y & 1)
+   addr = x < hdc->bwidth ? x & (hdc->hwidth - 1) : hdc->bwidth - 1;
+   if (y & 1)
addr += hdc->hwidth;
-   if (lcd->addr.y & 2)
+   if (y & 2)
addr += hdc->bwidth;
hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
return 0;
@@ -71,9 +70,7 @@ EXPORT_SYMBOL_GPL(hd44780_common_gotoxy);
 
 int hd44780_common_home(struct charlcd *lcd)
 {
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   return hd44780_common_gotoxy(lcd);
+   return hd44780_common_gotoxy(lcd, 0, 0);
 }
 EXPORT_SYMBOL_GPL(hd44780_common_home);
 
@@ -347,7 +344,7

[PATCH v4 16/32] auxdisplay: Implement hd44780_common_display_shift

2020-10-05 Thread poeschel
From: Lars Poeschel 

Implement a hd44780_common_display_shift function for hd44780 drivers to
use. charlcd uses this through its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 10 ++
 drivers/auxdisplay/charlcd.h|  2 ++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 16 
 drivers/auxdisplay/hd44780_common.h |  2 ++
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 85747e13bf48..e48287197732 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -31,10 +31,6 @@
 #define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
 #define LCD_CMD_BLINK_ON   0x01/* Set blink on */
 
-#define LCD_CMD_SHIFT  0x10/* Shift cursor/display */
-#define LCD_CMD_DISPLAY_SHIFT  0x08/* Shift display instead of cursor */
-#define LCD_CMD_SHIFT_RIGHT0x04/* Shift display/cursor to the right */
-
 #define LCD_CMD_FUNCTION_SET   0x20/* Set function */
 #define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
 #define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
@@ -303,13 +299,11 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'L':   /* shift display left */
-   hdc->write_cmd(hdc, LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT);
+   lcd->ops->shift_display(lcd, CHARLCD_SHIFT_LEFT);
processed = 1;
break;
case 'R':   /* shift display right */
-   hdc->write_cmd(hdc,
-   LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT |
-   LCD_CMD_SHIFT_RIGHT);
+   lcd->ops->shift_display(lcd, CHARLCD_SHIFT_RIGHT);
processed = 1;
break;
case 'k': { /* kill end of line */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 0a340beacd3e..6fd4a77f5794 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -59,6 +59,7 @@ struct charlcd {
  * function.
  * @init_display: Initialize the display.
  * @shift_cursor: Shift cursor left or right one position.
+ * @shift_display: Shift whole display content left or right.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -69,6 +70,7 @@ struct charlcd_ops {
int (*clear_display)(struct charlcd *lcd);
int (*init_display)(struct charlcd *lcd);
int (*shift_cursor)(struct charlcd *lcd, enum charlcd_shift_dir dir);
+   int (*shift_display)(struct charlcd *lcd, enum charlcd_shift_dir dir);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 6ffeeb3fb0d0..a3b18bbc2e4a 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -132,6 +132,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.clear_display  = hd44780_common_clear_display,
.init_display   = hd44780_common_init_display,
.shift_cursor   = hd44780_common_shift_cursor,
+   .shift_display  = hd44780_common_shift_display,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -181,6 +182,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.clear_display  = hd44780_common_clear_display,
.init_display   = hd44780_common_init_display,
.shift_cursor   = hd44780_common_shift_cursor,
+   .shift_display  = hd44780_common_shift_display,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 894a195eda39..972c74a22294 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -18,6 +18,7 @@
 #define LCD_CMD_BLINK_ON   0x01/* Set blink on */
 
 #define LCD_CMD_SHIFT  0x10/* Shift cursor/display */
+#define LCD_CMD_DISPLAY_SHIFT  0x08/* Shift display instead of cursor */
 #define LCD_CMD_SHIFT_RIGHT0x04/* Shift display/cursor to the right */
 
 #define LCD_CMD_FUNCTION_SET   0x20/* Set function */
@@ -180,6 +181,21 @@ int hd44780_common_shift_cursor(struct charlcd *lcd, enum 
charlcd_shift_dir dir)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_shift_cursor);
 
+int hd44780_common_shift_display(struct charlcd *lcd,
+   enum charlcd_shift_dir dir)
+{
+   struct hd44780_common *hdc = lcd->drvdata;
+
+   if (dir == CHARLCD_SHIFT_LEFT)
+   hdc->write_cmd(hdc, LCD_CMD_SHIFT | LCD_CMD_DISPLAY_SHIFT);
+   else if (dir == CHARLCD_SHIFT_RIGHT)
+   hdc->write_cmd(hdc, LCD_CMD_SH

[PATCH v4 31/32] auxdisplay: lcd2s DT binding doc

2020-10-05 Thread poeschel
From: Lars Poeschel 

Add a binding doc for the modtronix lcd2s auxdisplay driver. It also
adds modtronix to the list of known vendor-prefixes.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v3:
- Fixed make dt_binding_doc errors
Changes in v2:
- Adopted yaml based file format
---
 .../bindings/auxdisplay/modtronix,lcd2s.yaml  | 58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |  2 +
 2 files changed, 60 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml

diff --git a/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml 
b/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
new file mode 100644
index ..a1d55a2634a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/auxdisplay/modtronix,lcd2s.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Modtronix engineering LCD2S Character LCD Display
+
+maintainers:
+  - Lars Poeschel 
+
+description:
+  The LCD2S is a Character LCD Display manufactured by Modtronix Engineering.
+  The display supports a serial I2C and SPI interface. The driver currently
+  only supports the I2C interface.
+
+properties:
+  compatible:
+const: modtronix,lcd2s
+
+  reg:
+maxItems: 1
+description:
+  I2C bus address of the display.
+
+  display-height-chars:
+description: Height of the display, in character cells.
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 1
+maximum: 4
+
+  display-width-chars:
+description: Width of the display, in character cells.
+$ref: /schemas/types.yaml#/definitions/uint32
+minimum: 16
+maximum: 20
+
+required:
+  - compatible
+  - reg
+  - display-height-chars
+  - display-width-chars
+
+additionalProperties: false
+
+examples:
+  - |
+i2c {
+  #address-cells = <1>;
+  #size-cells = <0>;
+
+  lcd2s: auxdisplay@28 {
+compatible = "modtronix,lcd2s";
+reg = <0x28>;
+display-height-chars = <4>;
+display-width-chars = <20>;
+  };
+};
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml 
b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 63996ab03521..a9dd168db6ce 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -667,6 +667,8 @@ patternProperties:
 description: MiraMEMS Sensing Technology Co., Ltd.
   "^mitsubishi,.*":
 description: Mitsubishi Electric Corporation
+  "^modtronix,.*":
+description: Modtronix Engineering
   "^mosaixtech,.*":
 description: Mosaix Technologies, Inc.
   "^motorola,.*":
-- 
2.28.0



[PATCH v4 17/32] auxdisplay: Implement a hd44780_common_display

2020-10-05 Thread poeschel
From: Lars Poeschel 

Implement a hd44780_common_display function to turn the whole display on
or off. The hd44780 drivers can use this and charlcd uses this through
its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c|  6 ++
 drivers/auxdisplay/charlcd.h|  2 ++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 26 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 40 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index e48287197732..9bd3c0f2c470 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -232,10 +232,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
switch (*esc) {
case 'D':   /* Display ON */
priv->flags |= LCD_FLAG_D;
+   if (priv->flags != oldflags)
+   lcd->ops->display(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'd':   /* Display OFF */
priv->flags &= ~LCD_FLAG_D;
+   if (priv->flags != oldflags)
+   lcd->ops->display(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case 'C':   /* Cursor ON */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 6fd4a77f5794..ec739a25195e 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -60,6 +60,7 @@ struct charlcd {
  * @init_display: Initialize the display.
  * @shift_cursor: Shift cursor left or right one position.
  * @shift_display: Shift whole display content left or right.
+ * @display: Turn display on or off.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -71,6 +72,7 @@ struct charlcd_ops {
int (*init_display)(struct charlcd *lcd);
int (*shift_cursor)(struct charlcd *lcd, enum charlcd_shift_dir dir);
int (*shift_display)(struct charlcd *lcd, enum charlcd_shift_dir dir);
+   int (*display)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index a3b18bbc2e4a..0f76b812fa20 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -133,6 +133,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.init_display   = hd44780_common_init_display,
.shift_cursor   = hd44780_common_shift_cursor,
.shift_display  = hd44780_common_shift_display,
+   .display= hd44780_common_display,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -183,6 +184,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.init_display   = hd44780_common_init_display,
.shift_cursor   = hd44780_common_shift_cursor,
.shift_display  = hd44780_common_shift_display,
+   .display= hd44780_common_display,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 972c74a22294..07fd03555e99 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -196,6 +196,32 @@ int hd44780_common_shift_display(struct charlcd *lcd,
 }
 EXPORT_SYMBOL_GPL(hd44780_common_shift_display);
 
+static void hd44780_common_set_mode(struct hd44780_common *hdc)
+{
+   hdc->write_cmd(hdc,
+   LCD_CMD_DISPLAY_CTRL |
+   ((hdc->hd44780_common_flags & LCD_FLAG_D) ?
+   LCD_CMD_DISPLAY_ON : 0) |
+   ((hdc->hd44780_common_flags & LCD_FLAG_C) ?
+   LCD_CMD_CURSOR_ON : 0) |
+   ((hdc->hd44780_common_flags & LCD_FLAG_B) ?
+   LCD_CMD_BLINK_ON : 0));
+}
+
+int hd44780_common_display(struct charlcd *lcd, enum charlcd_onoff on)
+{
+   struct hd44780_common *hdc = lcd->drvdata;
+
+   if (on == CHARLCD_ON)
+   hdc->hd44780_common_flags |= LCD_FLAG_D;
+   else
+   hdc->hd44780_common_flags &= ~LCD_FLAG_D;
+
+   hd44780_common_set_mode(hdc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_display);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 7badb96cb8a9..1550fa77b956 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -24,5 +24,6 @@ int hd44780_common_shift_cursor(struct charlcd *lcd,
enum charlcd_shift_dir dir);
 int hd44780_common_shift_display(struct charlcd *lcd,
enum charlcd_shift_dir dir);
+int hd44780_co

[PATCH v4 21/32] auxdisplay: Implement hd44780_common_fontsize

2020-10-05 Thread poeschel
From: Lars Poeschel 

This implements hd44780_common_fontsize to switch between two fontsizes.
The hd44780 drivers can just set this function to their ops structure
and charlcd uses it through this ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c|  6 ++
 drivers/auxdisplay/charlcd.h|  6 ++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 25 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 43 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index c04aaa4d66a5..f4400a2c1ba5 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -281,10 +281,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'f':   /* Small Font */
priv->flags &= ~LCD_FLAG_F;
+   if (priv->flags != oldflags)
+   lcd->ops->fontsize(lcd, CHARLCD_FONTSIZE_SMALL);
+
processed = 1;
break;
case 'F':   /* Large Font */
priv->flags |= LCD_FLAG_F;
+   if (priv->flags != oldflags)
+   lcd->ops->fontsize(lcd, CHARLCD_FONTSIZE_LARGE);
+
processed = 1;
break;
case 'n':   /* One Line */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index d9d907db2724..ff223ed59bd9 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -26,6 +26,11 @@ enum charlcd_shift_dir {
CHARLCD_SHIFT_RIGHT,
 };
 
+enum charlcd_fontsize {
+   CHARLCD_FONTSIZE_SMALL,
+   CHARLCD_FONTSIZE_LARGE,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -77,6 +82,7 @@ struct charlcd_ops {
int (*display)(struct charlcd *lcd, enum charlcd_onoff on);
int (*cursor)(struct charlcd *lcd, enum charlcd_onoff on);
int (*blink)(struct charlcd *lcd, enum charlcd_onoff on);
+   int (*fontsize)(struct charlcd *lcd, enum charlcd_fontsize size);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index a8d6e5483a92..2b5f8984fcd4 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -136,6 +136,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.display= hd44780_common_display,
.cursor = hd44780_common_cursor,
.blink  = hd44780_common_blink,
+   .fontsize   = hd44780_common_fontsize,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -189,6 +190,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.display= hd44780_common_display,
.cursor = hd44780_common_cursor,
.blink  = hd44780_common_blink,
+   .fontsize   = hd44780_common_fontsize,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 5c028f157fc8..112285f8f414 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -250,6 +250,31 @@ int hd44780_common_blink(struct charlcd *lcd, enum 
charlcd_onoff on)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_blink);
 
+static void hd44780_common_set_function(struct hd44780_common *hdc)
+{
+   hdc->write_cmd(hdc,
+   LCD_CMD_FUNCTION_SET |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->hd44780_common_flags & LCD_FLAG_F) ?
+   LCD_CMD_FONT_5X10_DOTS : 0) |
+   ((hdc->hd44780_common_flags & LCD_FLAG_N) ?
+   LCD_CMD_TWO_LINES : 0));
+}
+
+int hd44780_common_fontsize(struct charlcd *lcd, enum charlcd_fontsize size)
+{
+   struct hd44780_common *hdc = lcd->drvdata;
+
+   if (size == CHARLCD_FONTSIZE_LARGE)
+   hdc->hd44780_common_flags |= LCD_FLAG_F;
+   else
+   hdc->hd44780_common_flags &= ~LCD_FLAG_F;
+
+   hd44780_common_set_function(hdc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_fontsize);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index b46171f21a05..65d513efcc43 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -27,5 +27,6 @@ int hd44780_common_shift_display(struct charlcd *lcd,
 int hd44780_common_display(struct charlcd *lcd, enum charlcd_onoff on);
 int hd44780_common_cursor(struct charlcd *lcd, enum charlcd_onoff on);
 int hd44780_c

[PATCH v4 19/32] auxdisplay: Implement hd44780_common_blink

2020-10-05 Thread poeschel
From: Lars Poeschel 

Implement a hd44780_common_blink function to turn on or off the blinking
of the cursor. The hd44780 drivers just use this function and charlcd
calls it through its ops function pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c|  6 ++
 drivers/auxdisplay/charlcd.h|  2 ++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 14 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 28 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index a2f0becb1a9f..b099897e101b 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -260,10 +260,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'B':   /* Blink ON */
priv->flags |= LCD_FLAG_B;
+   if (priv->flags != oldflags)
+   lcd->ops->blink(lcd, CHARLCD_ON);
+
processed = 1;
break;
case 'b':   /* Blink OFF */
priv->flags &= ~LCD_FLAG_B;
+   if (priv->flags != oldflags)
+   lcd->ops->blink(lcd, CHARLCD_OFF);
+
processed = 1;
break;
case '+':   /* Back light ON */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5aab359ebd91..d9d907db2724 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -62,6 +62,7 @@ struct charlcd {
  * @shift_display: Shift whole display content left or right.
  * @display: Turn display on or off.
  * @cursor: Turn cursor on or off.
+ * @blink: Turn cursor blink on or off.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -75,6 +76,7 @@ struct charlcd_ops {
int (*shift_display)(struct charlcd *lcd, enum charlcd_shift_dir dir);
int (*display)(struct charlcd *lcd, enum charlcd_onoff on);
int (*cursor)(struct charlcd *lcd, enum charlcd_onoff on);
+   int (*blink)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index d5ce3955b577..a8d6e5483a92 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -135,6 +135,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.shift_display  = hd44780_common_shift_display,
.display= hd44780_common_display,
.cursor = hd44780_common_cursor,
+   .blink  = hd44780_common_blink,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -187,6 +188,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.shift_display  = hd44780_common_shift_display,
.display= hd44780_common_display,
.cursor = hd44780_common_cursor,
+   .blink  = hd44780_common_blink,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 587385e55bae..5c028f157fc8 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -236,6 +236,20 @@ int hd44780_common_cursor(struct charlcd *lcd, enum 
charlcd_onoff on)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_cursor);
 
+int hd44780_common_blink(struct charlcd *lcd, enum charlcd_onoff on)
+{
+   struct hd44780_common *hdc = lcd->drvdata;
+
+   if (on == CHARLCD_ON)
+   hdc->hd44780_common_flags |= LCD_FLAG_B;
+   else
+   hdc->hd44780_common_flags &= ~LCD_FLAG_B;
+
+   hd44780_common_set_mode(hdc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_blink);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 7327a9b2e997..b46171f21a05 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -26,5 +26,6 @@ int hd44780_common_shift_display(struct charlcd *lcd,
enum charlcd_shift_dir dir);
 int hd44780_common_display(struct charlcd *lcd, enum charlcd_onoff on);
 int hd44780_common_cursor(struct charlcd *lcd, enum charlcd_onoff on);
+int hd44780_common_blink(struct charlcd *lcd, enum charlcd_onoff on);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 26fbf91c1501..2d2f59360e1a 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -883,6 +883,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
.shift_display  = hd44780_common_shift_display,
.display= hd44780_common_display,
.cursor   

[PATCH v4 22/32] auxdisplay: Implement hd44780_common_lines

2020-10-05 Thread poeschel
From: Lars Poeschel 

This implements hd44780_common_lines to switch the display between one
and two lines mode. The hd44780 drivers use this function by adding it
to their ops structure and charlcd now calls through its ops function
pointer.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c|  6 ++
 drivers/auxdisplay/charlcd.h|  7 +++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 14 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 33 insertions(+)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index f4400a2c1ba5..d672e4c371e1 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -295,10 +295,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
break;
case 'n':   /* One Line */
priv->flags &= ~LCD_FLAG_N;
+   if (priv->flags != oldflags)
+   lcd->ops->lines(lcd, CHARLCD_LINES_1);
+
processed = 1;
break;
case 'N':   /* Two Lines */
priv->flags |= LCD_FLAG_N;
+   if (priv->flags != oldflags)
+   lcd->ops->lines(lcd, CHARLCD_LINES_2);
+
processed = 1;
break;
case 'l':   /* Shift Cursor Left */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index ff223ed59bd9..5b0717c7482b 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -31,6 +31,11 @@ enum charlcd_fontsize {
CHARLCD_FONTSIZE_LARGE,
 };
 
+enum charlcd_lines {
+   CHARLCD_LINES_1,
+   CHARLCD_LINES_2,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -68,6 +73,7 @@ struct charlcd {
  * @display: Turn display on or off.
  * @cursor: Turn cursor on or off.
  * @blink: Turn cursor blink on or off.
+ * @lines: One or two lines.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -83,6 +89,7 @@ struct charlcd_ops {
int (*cursor)(struct charlcd *lcd, enum charlcd_onoff on);
int (*blink)(struct charlcd *lcd, enum charlcd_onoff on);
int (*fontsize)(struct charlcd *lcd, enum charlcd_fontsize size);
+   int (*lines)(struct charlcd *lcd, enum charlcd_lines lines);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 2b5f8984fcd4..7b7b28d72198 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -137,6 +137,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.cursor = hd44780_common_cursor,
.blink  = hd44780_common_blink,
.fontsize   = hd44780_common_fontsize,
+   .lines  = hd44780_common_lines,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -191,6 +192,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.cursor = hd44780_common_cursor,
.blink  = hd44780_common_blink,
.fontsize   = hd44780_common_fontsize,
+   .lines  = hd44780_common_lines,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 112285f8f414..2df2410f3874 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -275,6 +275,20 @@ int hd44780_common_fontsize(struct charlcd *lcd, enum 
charlcd_fontsize size)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_fontsize);
 
+int hd44780_common_lines(struct charlcd *lcd, enum charlcd_lines lines)
+{
+   struct hd44780_common *hdc = lcd->drvdata;
+
+   if (lines == CHARLCD_LINES_2)
+   hdc->hd44780_common_flags |= LCD_FLAG_N;
+   else
+   hdc->hd44780_common_flags &= ~LCD_FLAG_N;
+
+   hd44780_common_set_function(hdc);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_lines);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 65d513efcc43..419065bfaea2 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -28,5 +28,6 @@ int hd44780_common_display(struct charlcd *lcd, enum 
charlcd_onoff on);
 int hd44780_common_cursor(struct charlcd *lcd, enum charlcd_onoff on);
 int hd44780_common_blink(struct charlcd *lcd, enum charlcd_onoff on);
 int hd44780_common_fontsize(struct charlcd *lcd, enum charlcd_fontsize size);
+int hd44780_common_lines(struct charlcd *lcd, enum charlcd_lines lines);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/p

[PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

The init_display function is moved over to hd44780_common. charlcd uses
it via it's ops function pointer and drivers initialize the ops with the
common hd44780_common_init_display function.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 95 ++---
 drivers/auxdisplay/charlcd.h|  9 +++
 drivers/auxdisplay/hd44780.c|  2 +
 drivers/auxdisplay/hd44780_common.c | 88 ++
 drivers/auxdisplay/hd44780_common.h |  2 +
 drivers/auxdisplay/panel.c  |  3 +
 6 files changed, 110 insertions(+), 89 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 9631f70e8128..94f6b0afab13 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -8,7 +8,6 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -26,17 +25,7 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
 
-#define LCD_FLAG_B 0x0004  /* Blink on */
-#define LCD_FLAG_C 0x0008  /* Cursor on */
-#define LCD_FLAG_D 0x0010  /* Display on */
-#define LCD_FLAG_F 0x0020  /* Large font mode */
-#define LCD_FLAG_N 0x0040  /* 2-rows mode */
-#define LCD_FLAG_L 0x0080  /* Backlight enabled */
-
 /* LCD commands */
-#define LCD_CMD_ENTRY_MODE 0x04/* Set entry mode */
-#define LCD_CMD_CURSOR_INC 0x02/* Increment cursor */
-
 #define LCD_CMD_DISPLAY_CTRL   0x08/* Display control */
 #define LCD_CMD_DISPLAY_ON 0x04/* Set display on */
 #define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
@@ -84,12 +73,6 @@ struct charlcd_priv {
 /* Device single-open policy control */
 static atomic_t charlcd_available = ATOMIC_INIT(1);
 
-/* sleeps that many milliseconds with a reschedule */
-static void long_sleep(int ms)
-{
-   schedule_timeout_interruptible(msecs_to_jiffies(ms));
-}
-
 /* turn the backlight on or off */
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
@@ -177,76 +160,6 @@ static void charlcd_clear_fast(struct charlcd *lcd)
charlcd_home(lcd);
 }
 
-static int charlcd_init_display(struct charlcd *lcd)
-{
-   void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
-   struct hd44780_common *hdc = lcd->drvdata;
-   u8 init;
-
-   if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
-   return -EINVAL;
-
-   priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
- LCD_FLAG_C | LCD_FLAG_B;
-
-   long_sleep(20); /* wait 20 ms after power-up for the paranoid */
-
-   /*
-* 8-bit mode, 1 line, small fonts; let's do it 3 times, to make sure
-* the LCD is in 8-bit mode afterwards
-*/
-   init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
-   if (hdc->ifwidth == 4) {
-   init >>= 4;
-   write_cmd_raw = hdc->write_cmd_raw4;
-   } else {
-   write_cmd_raw = hdc->write_cmd;
-   }
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-   write_cmd_raw(hdc, init);
-   long_sleep(10);
-
-   if (hdc->ifwidth == 4) {
-   /* Switch to 4-bit mode, 1 line, small fonts */
-   hdc->write_cmd_raw4(hdc, LCD_CMD_FUNCTION_SET >> 4);
-   long_sleep(10);
-   }
-
-   /* set font height and lines number */
-   hdc->write_cmd(hdc,
-   LCD_CMD_FUNCTION_SET |
-   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-   ((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
-   ((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
-   long_sleep(10);
-
-   /* display off, cursor off, blink off */
-   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CTRL);
-   long_sleep(10);
-
-   hdc->write_cmd(hdc,
-   LCD_CMD_DISPLAY_CTRL |  /* set display mode */
-   ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
-   ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
-   ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
-
-   charlcd_backlight(lcd, (priv->flags & LCD_FLAG_L) ? 1 : 0);
-
-   long_sleep(10);
-
-   /* entry mode set : increment, cursor shifting */
-   hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
-
-   lcd->ops->clear_display(lcd);
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   return 0;
-}
-
 /*
  * Parses a movement command of the form "(.*);", where the group can be
  * any number of subcommands of the form "(x|y)[0-9]+".
@@ -418,7 +331,9 @@ st

[PATCH v4 20/32] auxdisplay: cleanup unnecessary hd44780 code in charlcd

2020-10-05 Thread poeschel
From: Lars Poeschel 

This cleans up now unnecessary hd44780 specific code from charlcd. We
obsoleted this with the last three patches. So another chunk of hd44780
code can be dropped.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 17 +
 1 file changed, 1 insertion(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index b099897e101b..c04aaa4d66a5 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -26,11 +26,6 @@
 #define LCD_BL_TEMPO_PERIOD4
 
 /* LCD commands */
-#define LCD_CMD_DISPLAY_CTRL   0x08/* Display control */
-#define LCD_CMD_DISPLAY_ON 0x04/* Set display on */
-#define LCD_CMD_CURSOR_ON  0x02/* Set cursor on */
-#define LCD_CMD_BLINK_ON   0x01/* Set blink on */
-
 #define LCD_CMD_FUNCTION_SET   0x20/* Set function */
 #define LCD_CMD_DATA_LEN_8BITS 0x10/* Set data length to 8 bits */
 #define LCD_CMD_TWO_LINES  0x08/* Set to two display lines */
@@ -419,17 +414,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (oldflags == priv->flags)
return processed;
 
-   /* check whether one of B,C,D flags were changed */
-   if ((oldflags ^ priv->flags) &
-   (LCD_FLAG_B | LCD_FLAG_C | LCD_FLAG_D))
-   /* set display mode */
-   hdc->write_cmd(hdc,
-   LCD_CMD_DISPLAY_CTRL |
-   ((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
-   ((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
-   ((priv->flags & LCD_FLAG_B) ? LCD_CMD_BLINK_ON : 0));
-   /* check whether one of F,N flags was changed */
-   else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
+   if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
hdc->write_cmd(hdc,
LCD_CMD_FUNCTION_SET |
((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
-- 
2.28.0



[PATCH v4 07/32] auxdisplay: Move addr out of charlcd_priv

2020-10-05 Thread poeschel
From: Lars Poeschel 

Move out the struct addr from struct charlcd_priv into the less private
struct charlcd. This member is used to pass position information. The
individual drivers need to be able to read this information, so we move
this out of charlcd_priv to charlcd structure.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 61 +++-
 drivers/auxdisplay/charlcd.h |  6 
 2 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index ce6622f71c34..1b37d4bc38f9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -72,12 +72,6 @@ struct charlcd_priv {
/* contains the LCD config state */
unsigned long int flags;
 
-   /* Contains the LCD X and Y offset */
-   struct {
-   unsigned long int x;
-   unsigned long int y;
-   } addr;
-
/* Current escape sequence and it's length or -1 if outside */
struct {
char buf[LCD_ESCAPE_LEN + 1];
@@ -148,7 +142,6 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
 
@@ -156,37 +149,34 @@ static void charlcd_gotoxy(struct charlcd *lcd)
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = priv->addr.x < hdc->bwidth ? priv->addr.x & (hdc->hwidth - 1)
+   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
  : hdc->bwidth - 1;
-   if (priv->addr.y & 1)
+   if (lcd->addr.y & 1)
addr += hdc->hwidth;
-   if (priv->addr.y & 2)
+   if (lcd->addr.y & 2)
addr += hdc->bwidth;
hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
-
-   priv->addr.x = 0;
-   priv->addr.y = 0;
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
charlcd_gotoxy(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
 
-   if (priv->addr.x < hdc->bwidth) {
+   if (lcd->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
hdc->write_data(hdc, c);
-   priv->addr.x++;
+   lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (priv->addr.x == hdc->bwidth)
+   if (lcd->addr.x == hdc->bwidth)
charlcd_gotoxy(lcd);
}
 }
@@ -210,12 +200,11 @@ static void charlcd_clear_fast(struct charlcd *lcd)
 /* clears the display and resets X/Y */
 static void charlcd_clear_display(struct charlcd *lcd)
 {
-   struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
 
hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   priv->addr.x = 0;
-   priv->addr.y = 0;
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
/* we must wait a few milliseconds (15) */
long_sleep(15);
 }
@@ -415,21 +404,21 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'l':   /* Shift Cursor Left */
-   if (priv->addr.x > 0) {
+   if (lcd->addr.x > 0) {
/* back one char if not at end of line */
-   if (priv->addr.x < hdc->bwidth)
+   if (lcd->addr.x < hdc->bwidth)
hdc->write_cmd(hdc, LCD_CMD_SHIFT);
-   priv->addr.x--;
+   lcd->addr.x--;
}
processed = 1;
break;
case 'r':   /* shift cursor right */
-   if (priv->addr.x < lcd->width) {
+   if (lcd->addr.x < lcd->width) {
/* allow the cursor to pass the end of the line */
-   if (priv->addr.x < (hdc->bwidth - 1))
+   if (lcd->addr.x < (hdc->bwidth - 1))
hdc->write_cmd(hdc,
LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
-   priv->addr.x++;
+   lcd->addr.x++;
}
processed = 1;
break;
@@ -446,7 +43

[PATCH v4 03/32] auxdisplay: Move hwidth and bwidth to struct hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

hwidth is for the hardware buffer size and bwidth is for the buffer
width of one single line. This is specific to the hd44780 displays and
so it is moved out from charlcd to struct hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 40 -
 drivers/auxdisplay/charlcd.h|  6 ++--
 drivers/auxdisplay/hd44780.c| 24 +--
 drivers/auxdisplay/hd44780_common.c |  3 +-
 drivers/auxdisplay/hd44780_common.h |  5 
 drivers/auxdisplay/panel.c  | 45 +++--
 6 files changed, 67 insertions(+), 56 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 8aaee0fea9ab..02392336d7d3 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -21,9 +21,7 @@
 #include 
 
 #include "charlcd.h"
-
-#define DEFAULT_LCD_BWIDTH  40
-#define DEFAULT_LCD_HWIDTH  64
+#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD4
@@ -151,18 +149,19 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
unsigned int addr;
 
/*
 * we force the cursor to stay at the end of the
 * line if it wants to go farther
 */
-   addr = priv->addr.x < lcd->bwidth ? priv->addr.x & (lcd->hwidth - 1)
- : lcd->bwidth - 1;
+   addr = priv->addr.x < hdc->bwidth ? priv->addr.x & (hdc->hwidth - 1)
+ : hdc->bwidth - 1;
if (priv->addr.y & 1)
-   addr += lcd->hwidth;
+   addr += hdc->hwidth;
if (priv->addr.y & 2)
-   addr += lcd->bwidth;
+   addr += hdc->bwidth;
lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
@@ -178,21 +177,23 @@ static void charlcd_home(struct charlcd *lcd)
 static void charlcd_print(struct charlcd *lcd, char c)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
-   if (priv->addr.x < lcd->bwidth) {
+   if (priv->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
lcd->ops->write_data(lcd, c);
priv->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (priv->addr.x == lcd->bwidth)
+   if (priv->addr.x == hdc->bwidth)
charlcd_gotoxy(lcd);
}
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
 {
+   struct hd44780_common *hdc = lcd->drvdata;
int pos;
 
charlcd_home(lcd);
@@ -200,7 +201,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
if (lcd->ops->clear_fast)
lcd->ops->clear_fast(lcd);
else
-   for (pos = 0; pos < min(2, lcd->height) * lcd->hwidth; pos++)
+   for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
lcd->ops->write_data(lcd, ' ');
 
charlcd_home(lcd);
@@ -348,6 +349,7 @@ static bool parse_xy(const char *s, unsigned long *x, 
unsigned long *y)
 static inline int handle_lcd_special_code(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
/* LCD special codes */
 
@@ -413,7 +415,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
case 'l':   /* Shift Cursor Left */
if (priv->addr.x > 0) {
/* back one char if not at end of line */
-   if (priv->addr.x < lcd->bwidth)
+   if (priv->addr.x < hdc->bwidth)
lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
priv->addr.x--;
}
@@ -422,7 +424,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
case 'r':   /* shift cursor right */
if (priv->addr.x < lcd->width) {
/* allow the cursor to pass the end of the line */
-   if (priv->addr.x < (lcd->bwidth - 1))
+   if (priv->addr.x < (hdc->bwidth - 1))
lcd->ops->write_cmd(lcd,
LCD_CMD_SHIFT | LCD_CMD_SHIFT_RIGHT);
priv->addr.x++;
@@ -442,7 +444,7 @@ static inline int handle_lcd_special_code(struct

[PATCH v4 01/32] auxdisplay: Use an enum for charlcd backlight on/off ops

2020-10-05 Thread poeschel
From: Lars Poeschel 

We use an enum for calling the functions in charlcd, that turn the
backlight on or off. This enum is generic and can be used for other
charlcd turn of / turn off operations as well.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 2 +-
 drivers/auxdisplay/charlcd.h | 7 ++-
 drivers/auxdisplay/hd44780.c | 2 +-
 drivers/auxdisplay/panel.c   | 2 +-
 4 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 5aee0f546351..8aaee0fea9ab 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -101,7 +101,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, int on)
+static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 00911ad0f3de..c66f038e5d2b 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -9,6 +9,11 @@
 #ifndef _CHARLCD_H
 #define _CHARLCD_H
 
+enum charlcd_onoff {
+   CHARLCD_OFF = 0,
+   CHARLCD_ON,
+};
+
 struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
@@ -30,7 +35,7 @@ struct charlcd_ops {
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
void (*clear_fast)(struct charlcd *lcd);
-   void (*backlight)(struct charlcd *lcd, int on);
+   void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
 };
 
 struct charlcd *charlcd_alloc(unsigned int drvdata_size);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index bcbe13092327..5982158557bb 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -37,7 +37,7 @@ struct hd44780 {
struct gpio_desc *pins[PIN_NUM];
 };
 
-static void hd44780_backlight(struct charlcd *lcd, int on)
+static void hd44780_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct hd44780 *hd = lcd->drvdata;
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 1c82d824ae00..de623ae219f1 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -708,7 +708,7 @@ static void lcd_send_serial(int byte)
 }
 
 /* turn the backlight on or off */
-static void lcd_backlight(struct charlcd *charlcd, int on)
+static void lcd_backlight(struct charlcd *charlcd, enum charlcd_onoff on)
 {
if (lcd.pins.bl == PIN_NONE)
return;
-- 
2.28.0



[PATCH v4 06/32] auxdisplay: Move write_cmd pointers to hd44780 drivers

2020-10-05 Thread poeschel
From: Lars Poeschel 

The write_cmd function is used to send commands to hd44780 displays.
The individual hd44780 drivers then implement their appropriate way of
doing this with their supported displays. So we move this pointer so
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 45 +++--
 drivers/auxdisplay/charlcd.h|  5 
 drivers/auxdisplay/hd44780.c| 15 --
 drivers/auxdisplay/hd44780_common.h |  3 ++
 drivers/auxdisplay/panel.c  | 12 
 5 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index df54078656c1..ce6622f71c34 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -162,7 +162,7 @@ static void charlcd_gotoxy(struct charlcd *lcd)
addr += hdc->hwidth;
if (priv->addr.y & 2)
addr += hdc->bwidth;
-   lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
+   hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
@@ -211,8 +211,9 @@ static void charlcd_clear_fast(struct charlcd *lcd)
 static void charlcd_clear_display(struct charlcd *lcd)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
 
-   lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CLEAR);
+   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
priv->addr.x = 0;
priv->addr.y = 0;
/* we must wait a few milliseconds (15) */
@@ -221,7 +222,7 @@ static void charlcd_clear_display(struct charlcd *lcd)
 
 static int charlcd_init_display(struct charlcd *lcd)
 {
-   void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
+   void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
struct charlcd_priv *priv = charlcd_to_priv(lcd);
struct hd44780_common *hdc = lcd->drvdata;
u8 init;
@@ -241,25 +242,25 @@ static int charlcd_init_display(struct charlcd *lcd)
init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
if (hdc->ifwidth == 4) {
init >>= 4;
-   write_cmd_raw = lcd->ops->write_cmd_raw4;
+   write_cmd_raw = hdc->write_cmd_raw4;
} else {
-   write_cmd_raw = lcd->ops->write_cmd;
+   write_cmd_raw = hdc->write_cmd;
}
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
-   write_cmd_raw(lcd, init);
+   write_cmd_raw(hdc, init);
long_sleep(10);
 
if (hdc->ifwidth == 4) {
/* Switch to 4-bit mode, 1 line, small fonts */
-   lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
+   hdc->write_cmd_raw4(hdc, LCD_CMD_FUNCTION_SET >> 4);
long_sleep(10);
}
 
/* set font height and lines number */
-   lcd->ops->write_cmd(lcd,
+   hdc->write_cmd(hdc,
LCD_CMD_FUNCTION_SET |
((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
@@ -267,10 +268,10 @@ static int charlcd_init_display(struct charlcd *lcd)
long_sleep(10);
 
/* display off, cursor off, blink off */
-   lcd->ops->write_cmd(lcd, LCD_CMD_DISPLAY_CTRL);
+   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CTRL);
long_sleep(10);
 
-   lcd->ops->write_cmd(lcd,
+   hdc->write_cmd(hdc,
LCD_CMD_DISPLAY_CTRL |  /* set display mode */
((priv->flags & LCD_FLAG_D) ? LCD_CMD_DISPLAY_ON : 0) |
((priv->flags & LCD_FLAG_C) ? LCD_CMD_CURSOR_ON : 0) |
@@ -281,7 +282,7 @@ static int charlcd_init_display(struct charlcd *lcd)
long_sleep(10);
 
/* entry mode set : increment, cursor shifting */
-   lcd->ops->write_cmd(lcd, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
+   hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
 
charlcd_clear_display(lcd);
return 0;
@@ -417,7 +418,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (priv->addr.x > 0) {
/* back one char if not at end of line */
if (priv->addr.x < hdc->bwidth)
-   lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
+   hdc->write_cmd(hdc, LCD_CMD_SHIFT);
priv->addr.x--;
}
processed = 1;
@@ -426,18 +427,18 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
if (priv->addr.x < lcd-

[PATCH v4 05/32] auxdisplay: Move write_data pointer to hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

This moves the write_data function pointer from struct charlcd_ops to
struct hd44780_common. This is the function that actually writes the
character to the display. This hd44780 hardware specific function is
used by two drivers at the moment.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 12 ++--
 drivers/auxdisplay/charlcd.h|  1 -
 drivers/auxdisplay/hd44780.c| 16 +---
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  | 12 ++--
 5 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 59e0a815bf3d..df54078656c1 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -182,7 +182,7 @@ static void charlcd_print(struct charlcd *lcd, char c)
if (priv->addr.x < hdc->bwidth) {
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
-   lcd->ops->write_data(lcd, c);
+   hdc->write_data(hdc, c);
priv->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
@@ -202,7 +202,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
lcd->ops->clear_fast(lcd);
else
for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
 
charlcd_home(lcd);
 }
@@ -446,7 +446,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
int x;
 
for (x = priv->addr.x; x < hdc->bwidth; x++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
 
/* restore cursor position */
charlcd_gotoxy(lcd);
@@ -505,7 +505,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
lcd->ops->write_cmd(lcd, LCD_CMD_SET_CGRAM_ADDR | (cgaddr * 8));
for (addr = 0; addr < cgoffset; addr++)
-   lcd->ops->write_data(lcd, cgbytes[addr]);
+   hdc->write_data(hdc, cgbytes[addr]);
 
/* ensures that we stop writing to CGRAM */
charlcd_gotoxy(lcd);
@@ -587,7 +587,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
priv->addr.x--;
}
/* replace with a space */
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
/* back one char again */
lcd->ops->write_cmd(lcd, LCD_CMD_SHIFT);
break;
@@ -601,7 +601,7 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * go to the beginning of the next line
 */
for (; priv->addr.x < hdc->bwidth; priv->addr.x++)
-   lcd->ops->write_data(lcd, ' ');
+   hdc->write_data(hdc, ' ');
priv->addr.x = 0;
priv->addr.y = (priv->addr.y + 1) % lcd->height;
charlcd_gotoxy(lcd);
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 5dce9dd36562..fba4f2cd42c4 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -27,7 +27,6 @@ struct charlcd {
 struct charlcd_ops {
/* Required */
void (*write_cmd)(struct charlcd *lcd, int cmd);
-   void (*write_data)(struct charlcd *lcd, int data);
 
/* Optional */
void (*write_cmd_raw4)(struct charlcd *lcd, int cmd);   /* 4-bit only */
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index f6786239c36f..922f0e0d2e6d 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -115,9 +115,8 @@ static void hd44780_write_cmd_gpio8(struct charlcd *lcd, 
int cmd)
 }
 
 /* Send data to the LCD panel in 8 bit GPIO mode */
-static void hd44780_write_data_gpio8(struct charlcd *lcd, int data)
+static void hd44780_write_data_gpio8(struct hd44780_common *hdc, int data)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
struct hd44780 *hd = hdc->hd44780;
 
hd44780_write_gpio8(hd, data, 1);
@@ -128,7 +127,6 @@ static void hd44780_write_data_gpio8(struct charlcd *lcd, 
int data)
 
 static const struct charlcd_ops hd44780_ops_gpio8 = {
.write_cmd  = hd44780_write_cmd_gpio8,
-   .write_data = hd44780_write_data_gpio8,
.backlight  = hd44780_backlight,
 };
 
@@ -163,9 +161,8 @@ static void hd44780_write_cmd_raw_gpio4(struct charl

[PATCH v4 08/32] auxdisplay: hd44780_common_print

2020-10-05 Thread poeschel
From: Lars Poeschel 

We create a hd44780_common_print function. It is derived from the
original charlcd_print. charlcd_print becomes a device independent print
function, that then only calles via it's ops function pointers, into the
print function offered by drivers.

Reported-by: kernel test robot 
Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v3:
- Fix kernel test robot reported error: Missed EXPORT_SYMBOL_GPL
---
 drivers/auxdisplay/charlcd.c| 28 +++-
 drivers/auxdisplay/charlcd.h| 11 +++
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 14 ++
 drivers/auxdisplay/hd44780_common.h |  1 +
 5 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 1b37d4bc38f9..72ed004a8980 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -167,18 +167,15 @@ static void charlcd_home(struct charlcd *lcd)
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
-   struct hd44780_common *hdc = lcd->drvdata;
+   if (lcd->char_conv)
+   c = lcd->char_conv[(unsigned char)c];
 
-   if (lcd->addr.x < hdc->bwidth) {
-   if (lcd->char_conv)
-   c = lcd->char_conv[(unsigned char)c];
-   hdc->write_data(hdc, c);
+   if (!lcd->ops->print(lcd, c))
lcd->addr.x++;
 
-   /* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == hdc->bwidth)
-   charlcd_gotoxy(lcd);
-   }
+   /* prevents the cursor from wrapping onto the next line */
+   if (lcd->addr.x == lcd->width)
+   charlcd_gotoxy(lcd);
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
@@ -192,7 +189,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
lcd->ops->clear_fast(lcd);
else
for (pos = 0; pos < min(2, lcd->height) * hdc->hwidth; pos++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
 
charlcd_home(lcd);
 }
@@ -433,12 +430,16 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
processed = 1;
break;
case 'k': { /* kill end of line */
-   int x;
+   int x, xs, ys;
 
+   xs = lcd->addr.x;
+   ys = lcd->addr.y;
for (x = lcd->addr.x; x < hdc->bwidth; x++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
 
/* restore cursor position */
+   lcd->addr.x = xs;
+   lcd->addr.y = ys;
charlcd_gotoxy(lcd);
processed = 1;
break;
@@ -591,7 +592,8 @@ static void charlcd_write_char(struct charlcd *lcd, char c)
 * go to the beginning of the next line
 */
for (; lcd->addr.x < hdc->bwidth; lcd->addr.x++)
-   hdc->write_data(hdc, ' ');
+   lcd->ops->print(lcd, ' ');
+
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
charlcd_gotoxy(lcd);
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index ff4896af2189..874519f079b4 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -30,9 +30,20 @@ struct charlcd {
void *drvdata;
 };
 
+/**
+ * struct charlcd_ops - Functions used by charlcd. Drivers have to implement
+ * these.
+ * @clear_fast: Clear the whole display and set cursor to position 0, 0.
+ * @backlight: Turn backlight on or off. Optional.
+ * @print: just Print one character to the display at current cursor position.
+ * The cursor is advanced by charlcd.
+ * The buffered cursor position is advanced by charlcd. The cursor should not
+ * wrap to the next line at the end of a line.
+ */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
+   int (*print)(struct charlcd *lcd, int c);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index dc4738563298..9680bb611639 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -126,6 +126,7 @@ static void hd44780_write_data_gpio8(struct hd44780_common 
*hdc, int data)
 
 static const struct charlcd_ops hd44780_ops_gpio8 = {
.backlight  = hd44780_backlight,
+   .print  = hd44780_common_print,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -169,6 +17

[PATCH v4 02/32] auxdisplay: Introduce hd44780_common.[ch]

2020-10-05 Thread poeschel
From: Lars Poeschel 

There is some hd44780 specific code in charlcd and this code is used by
multiple drivers. To make charlcd independent from this device specific
code this has to be moved to a place where the multiple drivers can
share their common code. This common place is now introduced as
hd44780_common.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
Changes in v3:
- Fix some typos
---
 drivers/auxdisplay/Kconfig  | 20 ++
 drivers/auxdisplay/Makefile |  1 +
 drivers/auxdisplay/hd44780.c| 43 +++--
 drivers/auxdisplay/hd44780_common.c | 21 ++
 drivers/auxdisplay/hd44780_common.h |  8 ++
 drivers/auxdisplay/panel.c  | 18 ++--
 6 files changed, 94 insertions(+), 17 deletions(-)
 create mode 100644 drivers/auxdisplay/hd44780_common.c
 create mode 100644 drivers/auxdisplay/hd44780_common.h

diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 81757eeded68..a56171d1a1ba 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -14,12 +14,31 @@ menuconfig AUXDISPLAY
 
  If you say N, all options in this submenu will be skipped and 
disabled.
 
+config CHARLCD
+   tristate "Character LCD core support" if COMPILE_TEST
+   help
+ This is the base system for character-based LCD displays.
+ It makes no sense to have this alone, you select your display driver
+ and if it needs the charlcd core, it will select it automatically.
+ This is some character LCD core interface that multiple drivers can
+ use.
+
+config HD44780_COMMON
+   tristate "Common functions for HD44780 (and compatibles) LCD displays" 
if COMPILE_TEST
+   help
+ This is a module with the common symbols for HD44780 (and compatibles)
+ displays. This is the code that multiple other modules use. It is not
+ useful alone. If you have some sort of HD44780 compatible display,
+ you very likely use this. It is selected automatically by selecting
+ your concrete display.
+
 if AUXDISPLAY
 
 config HD44780
tristate "HD44780 Character LCD support"
depends on GPIOLIB || COMPILE_TEST
select CHARLCD
+   select HD44780_COMMON
help
  Enable support for Character LCDs using a HD44780 controller.
  The LCD is accessible through the /dev/lcd char device (10, 156).
@@ -168,6 +187,7 @@ menuconfig PARPORT_PANEL
tristate "Parallel port LCD/Keypad Panel support"
depends on PARPORT
select CHARLCD
+   select HD44780_COMMON
help
  Say Y here if you have an HD44780 or KS-0074 LCD connected to your
  parallel port. This driver also features 4 and 6-key keypads. The LCD
diff --git a/drivers/auxdisplay/Makefile b/drivers/auxdisplay/Makefile
index cf54b5efb07e..7e8a8c3eb3c3 100644
--- a/drivers/auxdisplay/Makefile
+++ b/drivers/auxdisplay/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_CHARLCD)  += charlcd.o
+obj-$(CONFIG_HD44780_COMMON)   += hd44780_common.o
 obj-$(CONFIG_ARM_CHARLCD)  += arm-charlcd.o
 obj-$(CONFIG_KS0108)   += ks0108.o
 obj-$(CONFIG_CFAG12864B)   += cfag12864b.o cfag12864bfb.o
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 5982158557bb..271dba9cd108 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -15,6 +15,7 @@
 #include 
 
 #include "charlcd.h"
+#include "hd44780_common.h"
 
 enum hd44780_pin {
/* Order does matter due to writing to GPIO array subsets! */
@@ -179,8 +180,9 @@ static int hd44780_probe(struct platform_device *pdev)
struct device *dev = >dev;
unsigned int i, base;
struct charlcd *lcd;
+   struct hd44780_common *hdc;
struct hd44780 *hd;
-   int ifwidth, ret;
+   int ifwidth, ret = -ENOMEM;
 
/* Required pins */
ifwidth = gpiod_count(dev, "data");
@@ -198,31 +200,39 @@ static int hd44780_probe(struct platform_device *pdev)
return -EINVAL;
}
 
+   hdc = hd44780_common_alloc();
+   if (!hdc)
+   return -ENOMEM;
+
lcd = charlcd_alloc(sizeof(struct hd44780));
if (!lcd)
-   return -ENOMEM;
+   goto fail1;
 
-   hd = lcd->drvdata;
+   hd = kzalloc(sizeof(struct hd44780), GFP_KERNEL);
+   if (!hd)
+   goto fail2;
 
+   hdc->hd44780 = hd;
+   lcd->drvdata = hdc;
for (i = 0; i < ifwidth; i++) {
hd->pins[base + i] = devm_gpiod_get_index(dev, "data", i,
  GPIOD_OUT_LOW);
if (IS_ERR(hd->pins[base + i])) {
ret = PTR_ERR(hd->pins[base + i]);
-   goto fail;
+   goto fail3;

[PATCH v4 04/32] auxdisplay: Move ifwidth to struct hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

Move struct charlcd member ifwidth to our new struct hd44780_common.
ifwidth is hd44780 device specific and is used by two drivers at the
moment, so we move it to a common place, where both can use this.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 12 ++--
 drivers/auxdisplay/charlcd.h|  1 -
 drivers/auxdisplay/hd44780.c|  2 +-
 drivers/auxdisplay/hd44780_common.c |  1 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 5 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 02392336d7d3..59e0a815bf3d 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -223,9 +223,10 @@ static int charlcd_init_display(struct charlcd *lcd)
 {
void (*write_cmd_raw)(struct charlcd *lcd, int cmd);
struct charlcd_priv *priv = charlcd_to_priv(lcd);
+   struct hd44780_common *hdc = lcd->drvdata;
u8 init;
 
-   if (lcd->ifwidth != 4 && lcd->ifwidth != 8)
+   if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
return -EINVAL;
 
priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
@@ -238,7 +239,7 @@ static int charlcd_init_display(struct charlcd *lcd)
 * the LCD is in 8-bit mode afterwards
 */
init = LCD_CMD_FUNCTION_SET | LCD_CMD_DATA_LEN_8BITS;
-   if (lcd->ifwidth == 4) {
+   if (hdc->ifwidth == 4) {
init >>= 4;
write_cmd_raw = lcd->ops->write_cmd_raw4;
} else {
@@ -251,7 +252,7 @@ static int charlcd_init_display(struct charlcd *lcd)
write_cmd_raw(lcd, init);
long_sleep(10);
 
-   if (lcd->ifwidth == 4) {
+   if (hdc->ifwidth == 4) {
/* Switch to 4-bit mode, 1 line, small fonts */
lcd->ops->write_cmd_raw4(lcd, LCD_CMD_FUNCTION_SET >> 4);
long_sleep(10);
@@ -260,7 +261,7 @@ static int charlcd_init_display(struct charlcd *lcd)
/* set font height and lines number */
lcd->ops->write_cmd(lcd,
LCD_CMD_FUNCTION_SET |
-   ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 0) |
((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
long_sleep(10);
@@ -543,7 +544,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
else if ((oldflags ^ priv->flags) & (LCD_FLAG_F | LCD_FLAG_N))
lcd->ops->write_cmd(lcd,
LCD_CMD_FUNCTION_SET |
-   ((lcd->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
+   ((hdc->ifwidth == 8) ? LCD_CMD_DATA_LEN_8BITS : 0) |
((priv->flags & LCD_FLAG_F) ? LCD_CMD_FONT_5X10_DOTS : 
0) |
((priv->flags & LCD_FLAG_N) ? LCD_CMD_TWO_LINES : 0));
/* check whether L flag was changed */
@@ -794,7 +795,6 @@ struct charlcd *charlcd_alloc(void)
priv->esc_seq.len = -1;
 
lcd = >lcd;
-   lcd->ifwidth = 8;
 
return lcd;
 }
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 2a12d07705a3..5dce9dd36562 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -18,7 +18,6 @@ struct charlcd {
const struct charlcd_ops *ops;
const unsigned char *char_conv; /* Optional */
 
-   int ifwidth;/* 4-bit or 8-bit (default) */
int height;
int width;
 
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 0603af8f2336..f6786239c36f 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -275,7 +275,7 @@ static int hd44780_probe(struct platform_device *pdev)
/* Optional properties */
device_property_read_u32(dev, "internal-buffer-width", >bwidth);
 
-   lcd->ifwidth = ifwidth;
+   hdc->ifwidth = ifwidth;
lcd->ops = ifwidth == 8 ? _ops_gpio8 : _ops_gpio4;
 
ret = charlcd_register(lcd);
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 34e6d292fde8..285073a00302 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -12,6 +12,7 @@ struct hd44780_common *hd44780_common_alloc(void)
if (!hd)
return NULL;
 
+   hd->ifwidth = 8;
hd->bwidth = DEFAULT_LCD_BWIDTH;
hd->hwidth = DEFAULT_LCD_HWIDTH;
return hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 3ff47d2c5691..1100e0a32394 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++

[PATCH v4 10/32] auxdisplay: add home to charlcd_ops

2020-10-05 Thread poeschel
From: Lars Poeschel 

This adds a home function to the charlcd_ops struct and offer an
implementation for hd44780_common. This implementation is used by our
two hd44780 drivers. This is to make charlcd device independent.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 2 +-
 drivers/auxdisplay/charlcd.h| 3 +++
 drivers/auxdisplay/hd44780.c| 2 ++
 drivers/auxdisplay/hd44780_common.c | 8 
 drivers/auxdisplay/hd44780_common.h | 1 +
 drivers/auxdisplay/panel.c  | 3 +++
 6 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index d6f971eea6ae..44dd6e02eaf9 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -144,7 +144,7 @@ static void charlcd_home(struct charlcd *lcd)
 {
lcd->addr.x = 0;
lcd->addr.y = 0;
-   lcd->ops->gotoxy(lcd);
+   lcd->ops->home(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 04fd241fe6d6..12c348c1a0ae 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -40,12 +40,15 @@ struct charlcd {
  * wrap to the next line at the end of a line.
  * @gotoxy: Set cursor to x, y. The x and y values to set the cursor to are
  * previously set in addr.x and addr.y by charlcd.
+ * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
+ * charlcd prior to calling this function.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
void (*backlight)(struct charlcd *lcd, enum charlcd_onoff on);
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
+   int (*home)(struct charlcd *lcd);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 4d9478f6e5ff..b0893ea49165 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -128,6 +128,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.backlight  = hd44780_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -173,6 +174,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.backlight  = hd44780_backlight,
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index 9e463b2fa03f..a0ce390c6b2e 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -41,6 +41,14 @@ int hd44780_common_gotoxy(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_gotoxy);
 
+int hd44780_common_home(struct charlcd *lcd)
+{
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
+   return hd44780_common_gotoxy(lcd);
+}
+EXPORT_SYMBOL_GPL(hd44780_common_home);
+
 struct hd44780_common *hd44780_common_alloc(void)
 {
struct hd44780_common *hd;
diff --git a/drivers/auxdisplay/hd44780_common.h 
b/drivers/auxdisplay/hd44780_common.h
index 0bee6c22761e..1365484963d8 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -16,5 +16,6 @@ struct hd44780_common {
 
 int hd44780_common_print(struct charlcd *lcd, int c);
 int hd44780_common_gotoxy(struct charlcd *lcd);
+int hd44780_common_home(struct charlcd *lcd);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 75894eacd12f..b1e874f07456 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -876,18 +876,21 @@ static const struct charlcd_ops charlcd_serial_ops = {
.clear_fast = lcd_clear_fast_s,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
.clear_fast = lcd_clear_fast_p8,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
.clear_fast = lcd_clear_fast_tilcd,
.backlight  = lcd_backlight,
.gotoxy = hd44780_common_gotoxy,
+   .home   = hd44780_common_home,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0



[PATCH v4 00/32] Make charlcd device independent

2020-10-05 Thread poeschel
From: Lars Poeschel 

This tries to make charlcd device independent. At the moment hd44780
device specific code is contained deep in charlcd. This moves this out
into a hd44780_common module, where the two hd44780 drivers we have at
the moment (hd44780 and panel) can use this from. The goal is that at
the end other drivers can use the charlcd interface.
I add one such driver at the end with the last patch.
I submitted this already some time ago, where the wish was so split
this into smaller chunks what I try to do with this new patchset.
Most of the patches pick one specific function in charlcd and move the
device specific code into hd44780_common.

As a note to patch 30:
This might slightly change behaviour.
On hd44780 displays with one or two lines the previous implementation
did still write characters to the buffer of the display even if they are
currently not visible. The shift_display command could be used so set
the "viewing window" to a new position in the buffer and then you could
see the characters previously written.
This described behaviour does not work for hd44780 displays with more
than two display lines. There simply is not enough buffer.
So the behaviour was a bit inconsistens across different displays.
The new behaviour is to stop writing character at the end of a visible
line, even if there would be room in the buffer. This allows us to have
an easy implementation, that should behave equal on all supported
displays. This is not hd44780 hardware dependents anymore.

Link: https://lore.kernel.org/lkml/20191016082430.5955-1-poesc...@lemonage.de/
Link: 
https://lore.kernel.org/lkml/CANiq72kS-u_Xd_m+2CQVh-JCncPf1XNXrXAZ=4z+mze8fwv...@mail.gmail.com/

Lars Poeschel (32):
  auxdisplay: Use an enum for charlcd  backlight on/off ops
  auxdisplay: Introduce hd44780_common.[ch]
  auxdisplay: Move hwidth and bwidth to struct hd44780_common
  auxdisplay: Move ifwidth to struct hd44780_common
  auxdisplay: Move write_data pointer to hd44780_common
  auxdisplay: Move write_cmd pointers to hd44780 drivers
  auxdisplay: Move addr out of charlcd_priv
  auxdisplay: hd44780_common_print
  auxdisplay: provide hd44780_common_gotoxy
  auxdisplay: add home to charlcd_ops
  auxdisplay: Move clear_display to hd44780_common
  auxdisplay: make charlcd_backlight visible to hd44780_common
  auxdisplay: Make use of enum for backlight on / off
  auxdisplay: Move init_display to hd44780_common
  auxdisplay: implement hd44780_common_shift_cursor
  auxdisplay: Implement hd44780_common_display_shift
  auxdisplay: Implement a hd44780_common_display
  auxdisplay: Implement hd44780_common_cursor
  auxdisplay: Implement hd44780_common_blink
  auxdisplay: cleanup unnecessary hd44780 code in charlcd
  auxdisplay: Implement hd44780_common_fontsize
  auxdisplay: Implement hd44780_common_lines
  auxdisplay: Remove unnecessary hd44780 from charlcd
  auxdisplay: Move char redefine code to hd44780_common
  auxdisplay: Call charlcd_backlight in place
  auxdisplay: hd44780_common: Reduce clear_display timeout
  auxdisplay: hd44780: Remove clear_fast
  auxdisplay: charlcd: replace last device specific stuff
  auxdisplay: Change gotoxy calling interface
  auxdisplay: charlcd: Do not print chars at end of line
  auxdisplay: lcd2s DT binding doc
  auxdisplay: add a driver for lcd2s character display

 .../bindings/auxdisplay/modtronix,lcd2s.yaml  |  58 +++
 .../devicetree/bindings/vendor-prefixes.yaml  |   2 +
 drivers/auxdisplay/Kconfig|  30 ++
 drivers/auxdisplay/Makefile   |   2 +
 drivers/auxdisplay/charlcd.c  | 412 +-
 drivers/auxdisplay/charlcd.h  |  86 +++-
 drivers/auxdisplay/hd44780.c  | 120 +++--
 drivers/auxdisplay/hd44780_common.c   | 368 
 drivers/auxdisplay/hd44780_common.h   |  34 ++
 drivers/auxdisplay/lcd2s.c| 409 +
 drivers/auxdisplay/panel.c| 180 
 11 files changed, 1251 insertions(+), 450 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/auxdisplay/modtronix,lcd2s.yaml
 create mode 100644 drivers/auxdisplay/hd44780_common.c
 create mode 100644 drivers/auxdisplay/hd44780_common.h
 create mode 100644 drivers/auxdisplay/lcd2s.c

-- 
2.28.0



[PATCH v4 12/32] auxdisplay: make charlcd_backlight visible to hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

hd44780_common wants to use the charlcd_backlight function, so make it
visible.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c | 3 ++-
 drivers/auxdisplay/charlcd.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index fc0daf4987d5..154419513186 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -91,7 +91,7 @@ static void long_sleep(int ms)
 }
 
 /* turn the backlight on or off */
-static void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
+void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on)
 {
struct charlcd_priv *priv = charlcd_to_priv(lcd);
 
@@ -103,6 +103,7 @@ static void charlcd_backlight(struct charlcd *lcd, enum 
charlcd_onoff on)
lcd->ops->backlight(lcd, on);
mutex_unlock(>bl_tempo_lock);
 }
+EXPORT_SYMBOL_GPL(charlcd_backlight);
 
 static void charlcd_bl_off(struct work_struct *work)
 {
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 0b3dafbbae72..e5b22e72fdc8 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -55,6 +55,7 @@ struct charlcd_ops {
int (*clear_display)(struct charlcd *lcd);
 };
 
+void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
 struct charlcd *charlcd_alloc(void);
 void charlcd_free(struct charlcd *lcd);
 
-- 
2.28.0



[PATCH v4 09/32] auxdisplay: provide hd44780_common_gotoxy

2020-10-05 Thread poeschel
From: Lars Poeschel 

Provide a hd44780_common_gotoxy function and a pointer in the ops for
charlcd to use to move the cursor.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 38 +
 drivers/auxdisplay/charlcd.h|  4 ++-
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 23 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 72ed004a8980..d6f971eea6ae 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -55,7 +55,7 @@
 
 #define LCD_CMD_SET_CGRAM_ADDR 0x40/* Set char generator RAM address */
 
-#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
+#define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
 
 #define LCD_ESCAPE_LEN 24  /* Max chars for LCD escape command */
 #define LCD_ESCAPE_CHAR27  /* Use char 27 for escape 
command */
@@ -140,33 +140,17 @@ void charlcd_poke(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(charlcd_poke);
 
-static void charlcd_gotoxy(struct charlcd *lcd)
-{
-   struct hd44780_common *hdc = lcd->drvdata;
-   unsigned int addr;
-
-   /*
-* we force the cursor to stay at the end of the
-* line if it wants to go farther
-*/
-   addr = lcd->addr.x < hdc->bwidth ? lcd->addr.x & (hdc->hwidth - 1)
- : hdc->bwidth - 1;
-   if (lcd->addr.y & 1)
-   addr += hdc->hwidth;
-   if (lcd->addr.y & 2)
-   addr += hdc->bwidth;
-   hdc->write_cmd(hdc, LCD_CMD_SET_DDRAM_ADDR | addr);
-}
-
 static void charlcd_home(struct charlcd *lcd)
 {
lcd->addr.x = 0;
lcd->addr.y = 0;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
 }
 
 static void charlcd_print(struct charlcd *lcd, char c)
 {
+   struct hd44780_common *hdc = lcd->drvdata;
+
if (lcd->char_conv)
c = lcd->char_conv[(unsigned char)c];
 
@@ -174,8 +158,8 @@ static void charlcd_print(struct charlcd *lcd, char c)
lcd->addr.x++;
 
/* prevents the cursor from wrapping onto the next line */
-   if (lcd->addr.x == lcd->width)
-   charlcd_gotoxy(lcd);
+   if (lcd->addr.x == hdc->bwidth)
+   lcd->ops->gotoxy(lcd);
 }
 
 static void charlcd_clear_fast(struct charlcd *lcd)
@@ -440,7 +424,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
/* restore cursor position */
lcd->addr.x = xs;
lcd->addr.y = ys;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
processed = 1;
break;
}
@@ -499,7 +483,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
hdc->write_data(hdc, cgbytes[addr]);
 
/* ensures that we stop writing to CGRAM */
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
processed = 1;
break;
}
@@ -510,7 +494,7 @@ static inline int handle_lcd_special_code(struct charlcd 
*lcd)
 
/* If the command is valid, move to the new address */
if (parse_xy(esc, >addr.x, >addr.y))
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
 
/* Regardless of its validity, mark as processed */
processed = 1;
@@ -596,12 +580,12 @@ static void charlcd_write_char(struct charlcd *lcd, char 
c)
 
lcd->addr.x = 0;
lcd->addr.y = (lcd->addr.y + 1) % lcd->height;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
break;
case '\r':
/* go to the beginning of the same line */
lcd->addr.x = 0;
-   charlcd_gotoxy(lcd);
+   lcd->ops->gotoxy(lcd);
break;
case '\t':
/* print a space instead of the tab */
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 874519f079b4..04fd241fe6d6 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -36,14 +36,16 @@ struct charlcd {
  * @clear_fast: Clear the whole display and set cursor to position 0, 0.
  * @backlight: Turn backlight on or off. Optional.
  * @print: just Print one character to the display at current cursor position.
- * The cursor is advanced by charlcd.
  * The buffered cursor position is

[PATCH v4 11/32] auxdisplay: Move clear_display to hd44780_common

2020-10-05 Thread poeschel
From: Lars Poeschel 

This moves the clear_display function from charlcd to hd44780_common.
This is one more step to make charlcd independent from device specific
code. The two hd44780 drivers use the new function from hd44780_common
and charlcd calls this function through its function pointer in its ops
structure.

Reviewed-by: Willy Tarreau 
Signed-off-by: Lars Poeschel 
---
 drivers/auxdisplay/charlcd.c| 22 ++
 drivers/auxdisplay/charlcd.h|  4 
 drivers/auxdisplay/hd44780.c|  2 ++
 drivers/auxdisplay/hd44780_common.c | 21 +
 drivers/auxdisplay/hd44780_common.h |  1 +
 drivers/auxdisplay/panel.c  |  3 +++
 6 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c
index 44dd6e02eaf9..fc0daf4987d5 100644
--- a/drivers/auxdisplay/charlcd.c
+++ b/drivers/auxdisplay/charlcd.c
@@ -34,8 +34,6 @@
 #define LCD_FLAG_L 0x0080  /* Backlight enabled */
 
 /* LCD commands */
-#define LCD_CMD_DISPLAY_CLEAR  0x01/* Clear entire display */
-
 #define LCD_CMD_ENTRY_MODE 0x04/* Set entry mode */
 #define LCD_CMD_CURSOR_INC 0x02/* Increment cursor */
 
@@ -178,18 +176,6 @@ static void charlcd_clear_fast(struct charlcd *lcd)
charlcd_home(lcd);
 }
 
-/* clears the display and resets X/Y */
-static void charlcd_clear_display(struct charlcd *lcd)
-{
-   struct hd44780_common *hdc = lcd->drvdata;
-
-   hdc->write_cmd(hdc, LCD_CMD_DISPLAY_CLEAR);
-   lcd->addr.x = 0;
-   lcd->addr.y = 0;
-   /* we must wait a few milliseconds (15) */
-   long_sleep(15);
-}
-
 static int charlcd_init_display(struct charlcd *lcd)
 {
void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
@@ -254,7 +240,9 @@ static int charlcd_init_display(struct charlcd *lcd)
/* entry mode set : increment, cursor shifting */
hdc->write_cmd(hdc, LCD_CMD_ENTRY_MODE | LCD_CMD_CURSOR_INC);
 
-   charlcd_clear_display(lcd);
+   lcd->ops->clear_display(lcd);
+   lcd->addr.x = 0;
+   lcd->addr.y = 0;
return 0;
 }
 
@@ -670,8 +658,10 @@ static int charlcd_open(struct inode *inode, struct file 
*file)
goto fail;
 
if (priv->must_clear) {
-   charlcd_clear_display(>lcd);
+   priv->lcd.ops->clear_display(>lcd);
priv->must_clear = false;
+   priv->lcd.addr.x = 0;
+   priv->lcd.addr.y = 0;
}
return nonseekable_open(inode, file);
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index 12c348c1a0ae..0b3dafbbae72 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -42,6 +42,9 @@ struct charlcd {
  * previously set in addr.x and addr.y by charlcd.
  * @home: Set cursor to 0, 0. The values in addr.x and addr.y are set to 0, 0 
by
  * charlcd prior to calling this function.
+ * @clear_display: Again clear the whole display, set the cursor to 0, 0. The
+ * values in addr.x and addr.y are set to 0, 0 by charlcd prior to calling this
+ * function.
  */
 struct charlcd_ops {
void (*clear_fast)(struct charlcd *lcd);
@@ -49,6 +52,7 @@ struct charlcd_ops {
int (*print)(struct charlcd *lcd, int c);
int (*gotoxy)(struct charlcd *lcd);
int (*home)(struct charlcd *lcd);
+   int (*clear_display)(struct charlcd *lcd);
 };
 
 struct charlcd *charlcd_alloc(void);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index b0893ea49165..40ea6d25dbe1 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -129,6 +129,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
+   .clear_display  = hd44780_common_clear_display,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -175,6 +176,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
.print  = hd44780_common_print,
.gotoxy = hd44780_common_gotoxy,
.home   = hd44780_common_home,
+   .clear_display  = hd44780_common_clear_display,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c 
b/drivers/auxdisplay/hd44780_common.c
index a0ce390c6b2e..6bc2b3bf6139 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -1,13 +1,22 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 #include 
+#include 
 #include 
 
 #include "charlcd.h"
 #include "hd44780_common.h"
 
 /* LCD commands */
+#define LCD_CMD_DISPLAY_CLEAR  0x01/* Clear entire display */
+
 #define LCD_CMD_SET_DDRAM_ADDR 0x80/* Set display data RAM address */
 
+/* sleeps that many milliseconds with a reschedule */
+s

  1   2   3   4   5   6   >