linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off
@ 2020-10-05 13:01 poeschel
  2020-10-05 13:01 ` [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common poeschel
                   ` (18 more replies)
  0 siblings, 19 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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

Reviewed-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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(&priv->lcd, 0);
+			priv->lcd.ops->backlight(&priv->lcd, CHARLCD_OFF);
 	}
 	mutex_unlock(&priv->bl_tempo_lock);
 }
@@ -132,7 +132,7 @@ void charlcd_poke(struct charlcd *lcd)
 
 	mutex_lock(&priv->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(&priv->bl_work, LCD_BL_TEMPO_PERIOD * HZ);
 	mutex_unlock(&priv->bl_tempo_lock);
@@ -829,7 +829,7 @@ int charlcd_unregister(struct charlcd *lcd)
 	the_charlcd = NULL;
 	if (lcd->ops->backlight) {
 		cancel_delayed_work_sync(&priv->bl_work);
-		priv->lcd.ops->backlight(&priv->lcd, 0);
+		priv->lcd.ops->backlight(&priv->lcd, CHARLCD_OFF);
 	}
 
 	return 0;
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-16  3:16   ` Miguel Ojeda
  2020-10-05 13:01 ` [PATCH v4 15/32] auxdisplay: implement hd44780_common_shift_cursor poeschel
                   ` (17 subsequent siblings)
  18 siblings, 1 reply; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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 <linux/atomic.h>
 #include <linux/ctype.h>
-#include <linux/delay.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
@@ -26,17 +25,7 @@
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD	4
 
-#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 @@ static inline int handle_lcd_special_code(struct charlcd *lcd)
 		break;
 	}
 	case 'I':	/* reinitialize display */
-		charlcd_init_display(lcd);
+		lcd->ops->init_display(lcd);
+		priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
+			LCD_FLAG_C | LCD_FLAG_B;
 		processed = 1;
 		break;
 	case 'G': {
@@ -727,6 +642,8 @@ static int charlcd_init(struct charlcd *lcd)
 	struct charlcd_priv *priv = charlcd_to_priv(lcd);
 	int ret;
 
+	priv->flags = ((lcd->height > 1) ? LCD_FLAG_N : 0) | LCD_FLAG_D |
+		      LCD_FLAG_C | LCD_FLAG_B;
 	if (lcd->ops->backlight) {
 		mutex_init(&priv->bl_tempo_lock);
 		INIT_DELAYED_WORK(&priv->bl_work, charlcd_bl_off);
@@ -737,7 +654,7 @@ static int charlcd_init(struct charlcd *lcd)
 	 * Since charlcd_init_display() needs to write data, we have to
 	 * enable mark the LCD initialized just before.
 	 */
-	ret = charlcd_init_display(lcd);
+	ret = lcd->ops->init_display(lcd);
 	if (ret)
 		return ret;
 
diff --git a/drivers/auxdisplay/charlcd.h b/drivers/auxdisplay/charlcd.h
index e5b22e72fdc8..6281cf299a6d 100644
--- a/drivers/auxdisplay/charlcd.h
+++ b/drivers/auxdisplay/charlcd.h
@@ -9,6 +9,13 @@
 #ifndef _CHARLCD_H
 #define _CHARLCD_H
 
+#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 */
+
 enum charlcd_onoff {
 	CHARLCD_OFF = 0,
 	CHARLCD_ON,
@@ -45,6 +52,7 @@ struct charlcd {
  * @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.
+ * @init_display: Initialize the display.
  */
 struct charlcd_ops {
 	void (*clear_fast)(struct charlcd *lcd);
@@ -53,6 +61,7 @@ struct charlcd_ops {
 	int (*gotoxy)(struct charlcd *lcd);
 	int (*home)(struct charlcd *lcd);
 	int (*clear_display)(struct charlcd *lcd);
+	int (*init_display)(struct charlcd *lcd);
 };
 
 void charlcd_backlight(struct charlcd *lcd, enum charlcd_onoff on);
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 40ea6d25dbe1..5916da09f738 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -130,6 +130,7 @@ static const struct charlcd_ops hd44780_ops_gpio8 = {
 	.gotoxy		= hd44780_common_gotoxy,
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
+	.init_display	= hd44780_common_init_display,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -177,6 +178,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
 	.gotoxy		= hd44780_common_gotoxy,
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
+	.init_display	= hd44780_common_init_display,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c
index 6bc2b3bf6139..8e64de2e44f2 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -9,6 +9,19 @@
 /* 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 */
+
+#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_DDRAM_ADDR	0x80	/* Set display data RAM address */
 
 /* sleeps that many milliseconds with a reschedule */
@@ -70,6 +83,81 @@ int hd44780_common_clear_display(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_clear_display);
 
+int hd44780_common_init_display(struct charlcd *lcd)
+{
+	struct hd44780_common *hdc = lcd->drvdata;
+
+	void (*write_cmd_raw)(struct hd44780_common *hdc, int cmd);
+	u8 init;
+
+	if (hdc->ifwidth != 4 && hdc->ifwidth != 8)
+		return -EINVAL;
+
+	hdc->hd44780_common_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) |
+		((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));
+	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 */
+		((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));
+
+	charlcd_backlight(lcd,
+			(hdc->hd44780_common_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);
+
+	hd44780_common_clear_display(lcd);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_init_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 11ec4baf6997..cefd78d67675 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -7,6 +7,7 @@ struct hd44780_common {
 	int ifwidth;			/* 4-bit or 8-bit (default) */
 	int bwidth;			/* Default set by hd44780_alloc() */
 	int hwidth;			/* Default set by hd44780_alloc() */
+	unsigned long hd44780_common_flags;
 	void (*write_data)(struct hd44780_common *hdc, int data);
 	void (*write_cmd)(struct hd44780_common *hdc, int cmd);
 	/* write_cmd_raw4 is for 4-bit connected displays only */
@@ -18,5 +19,6 @@ int hd44780_common_print(struct charlcd *lcd, int c);
 int hd44780_common_gotoxy(struct charlcd *lcd);
 int hd44780_common_home(struct charlcd *lcd);
 int hd44780_common_clear_display(struct charlcd *lcd);
+int hd44780_common_init_display(struct charlcd *lcd);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 8adf627529f1..583bd22d3abd 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -878,6 +878,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.gotoxy		= hd44780_common_gotoxy,
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
+	.init_display	= hd44780_common_init_display,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -886,6 +887,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.gotoxy		= hd44780_common_gotoxy,
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
+	.init_display	= hd44780_common_init_display,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -894,6 +896,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.gotoxy		= hd44780_common_gotoxy,
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
+	.init_display	= hd44780_common_init_display,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 15/32] auxdisplay: implement hd44780_common_shift_cursor
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
  2020-10-05 13:01 ` [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 16/32] auxdisplay: Implement hd44780_common_display_shift poeschel
                   ` (16 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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,
 	.clear_display	= hd44780_common_clear_display,
 	.init_display	= hd44780_common_init_display,
+	.shift_cursor	= hd44780_common_shift_cursor,
 };
 
 /* Send a command to the LCD panel in 4 bit GPIO mode */
@@ -179,6 +180,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
 	.init_display	= hd44780_common_init_display,
+	.shift_cursor	= hd44780_common_shift_cursor,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c
index 8e64de2e44f2..894a195eda39 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -17,6 +17,9 @@
 #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_SHIFT_RIGHT	0x04	/* 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 */
@@ -158,6 +161,25 @@ int hd44780_common_init_display(struct charlcd *lcd)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_init_display);
 
+int hd44780_common_shift_cursor(struct charlcd *lcd, enum charlcd_shift_dir dir)
+{
+	struct hd44780_common *hdc = lcd->drvdata;
+
+	if (dir == CHARLCD_SHIFT_LEFT) {
+		/* back one char if not at end of line */
+		if (lcd->addr.x < hdc->bwidth)
+			hdc->write_cmd(hdc, LCD_CMD_SHIFT);
+	} else if (dir == CHARLCD_SHIFT_RIGHT) {
+		/* 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);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_shift_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 cefd78d67675..432fc37213cf 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -20,5 +20,7 @@ int hd44780_common_gotoxy(struct charlcd *lcd);
 int hd44780_common_home(struct charlcd *lcd);
 int hd44780_common_clear_display(struct charlcd *lcd);
 int hd44780_common_init_display(struct charlcd *lcd);
+int hd44780_common_shift_cursor(struct charlcd *lcd,
+		enum charlcd_shift_dir dir);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 583bd22d3abd..4275223080e8 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -879,6 +879,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
 	.init_display	= hd44780_common_init_display,
+	.shift_cursor	= hd44780_common_shift_cursor,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -888,6 +889,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
 	.init_display	= hd44780_common_init_display,
+	.shift_cursor	= hd44780_common_shift_cursor,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -897,6 +899,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.home		= hd44780_common_home,
 	.clear_display	= hd44780_common_clear_display,
 	.init_display	= hd44780_common_init_display,
+	.shift_cursor	= hd44780_common_shift_cursor,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 16/32] auxdisplay: Implement hd44780_common_display_shift
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
  2020-10-05 13:01 ` [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common poeschel
  2020-10-05 13:01 ` [PATCH v4 15/32] auxdisplay: implement hd44780_common_shift_cursor poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 17/32] auxdisplay: Implement a hd44780_common_display poeschel
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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

Reviewed-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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_RIGHT	0x04	/* 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_RIGHT	0x04	/* 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_SHIFT | LCD_CMD_DISPLAY_SHIFT |
+			LCD_CMD_SHIFT_RIGHT);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_shift_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 432fc37213cf..7badb96cb8a9 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -22,5 +22,7 @@ int hd44780_common_clear_display(struct charlcd *lcd);
 int hd44780_common_init_display(struct charlcd *lcd);
 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);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 4275223080e8..7ebbfb338518 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -880,6 +880,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.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 const struct charlcd_ops charlcd_parallel_ops = {
@@ -890,6 +891,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.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 const struct charlcd_ops charlcd_tilcd_ops = {
@@ -900,6 +902,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.clear_display	= hd44780_common_clear_display,
 	.init_display	= hd44780_common_init_display,
 	.shift_cursor	= hd44780_common_shift_cursor,
+	.shift_display	= hd44780_common_shift_display,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 17/32] auxdisplay: Implement a hd44780_common_display
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (2 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 16/32] auxdisplay: Implement hd44780_common_display_shift poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 18/32] auxdisplay: Implement hd44780_common_cursor poeschel
                   ` (14 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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_common_display(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 7ebbfb338518..9cb895c74cfb 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -881,6 +881,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.init_display	= hd44780_common_init_display,
 	.shift_cursor	= hd44780_common_shift_cursor,
 	.shift_display	= hd44780_common_shift_display,
+	.display	= hd44780_common_display,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -892,6 +893,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.init_display	= hd44780_common_init_display,
 	.shift_cursor	= hd44780_common_shift_cursor,
 	.shift_display	= hd44780_common_shift_display,
+	.display	= hd44780_common_display,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -903,6 +905,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.init_display	= hd44780_common_init_display,
 	.shift_cursor	= hd44780_common_shift_cursor,
 	.shift_display	= hd44780_common_shift_display,
+	.display	= hd44780_common_display,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 18/32] auxdisplay: Implement hd44780_common_cursor
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (3 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 17/32] auxdisplay: Implement a hd44780_common_display poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 19/32] auxdisplay: Implement hd44780_common_blink poeschel
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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,
 	.display	= hd44780_common_display,
+	.cursor		= hd44780_common_cursor,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -894,6 +895,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.shift_cursor	= hd44780_common_shift_cursor,
 	.shift_display	= hd44780_common_shift_display,
 	.display	= hd44780_common_display,
+	.cursor		= hd44780_common_cursor,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -906,6 +908,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.shift_cursor	= hd44780_common_shift_cursor,
 	.shift_display	= hd44780_common_shift_display,
 	.display	= hd44780_common_display,
+	.cursor		= hd44780_common_cursor,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 19/32] auxdisplay: Implement hd44780_common_blink
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (4 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 18/32] auxdisplay: Implement hd44780_common_cursor poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 20/32] auxdisplay: cleanup unnecessary hd44780 code in charlcd poeschel
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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		= hd44780_common_cursor,
+	.blink		= hd44780_common_blink,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -896,6 +897,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.shift_display	= hd44780_common_shift_display,
 	.display	= hd44780_common_display,
 	.cursor		= hd44780_common_cursor,
+	.blink		= hd44780_common_blink,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -909,6 +911,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.shift_display	= hd44780_common_shift_display,
 	.display	= hd44780_common_display,
 	.cursor		= hd44780_common_cursor,
+	.blink		= hd44780_common_blink,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 20/32] auxdisplay: cleanup unnecessary hd44780 code in charlcd
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (5 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 19/32] auxdisplay: Implement hd44780_common_blink poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 21/32] auxdisplay: Implement hd44780_common_fontsize poeschel
                   ` (11 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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_PERIOD	4
 
 /* 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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 21/32] auxdisplay: Implement hd44780_common_fontsize
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (6 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 20/32] auxdisplay: cleanup unnecessary hd44780 code in charlcd poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 22/32] auxdisplay: Implement hd44780_common_lines poeschel
                   ` (10 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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_common_blink(struct charlcd *lcd, enum charlcd_onoff on);
+int hd44780_common_fontsize(struct charlcd *lcd, enum charlcd_fontsize size);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 2d2f59360e1a..6e13806af497 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -884,6 +884,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.display	= hd44780_common_display,
 	.cursor		= hd44780_common_cursor,
 	.blink		= hd44780_common_blink,
+	.fontsize	= hd44780_common_fontsize,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -898,6 +899,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.display	= hd44780_common_display,
 	.cursor		= hd44780_common_cursor,
 	.blink		= hd44780_common_blink,
+	.fontsize	= hd44780_common_fontsize,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -912,6 +914,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.display	= hd44780_common_display,
 	.cursor		= hd44780_common_cursor,
 	.blink		= hd44780_common_blink,
+	.fontsize	= hd44780_common_fontsize,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 22/32] auxdisplay: Implement hd44780_common_lines
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (7 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 21/32] auxdisplay: Implement hd44780_common_fontsize poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 23/32] auxdisplay: Remove unnecessary hd44780 from charlcd poeschel
                   ` (9 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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/panel.c b/drivers/auxdisplay/panel.c
index 6e13806af497..3d33d7cc979c 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -885,6 +885,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.cursor		= hd44780_common_cursor,
 	.blink		= hd44780_common_blink,
 	.fontsize	= hd44780_common_fontsize,
+	.lines		= hd44780_common_lines,
 };
 
 static const struct charlcd_ops charlcd_parallel_ops = {
@@ -900,6 +901,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.cursor		= hd44780_common_cursor,
 	.blink		= hd44780_common_blink,
 	.fontsize	= hd44780_common_fontsize,
+	.lines		= hd44780_common_lines,
 };
 
 static const struct charlcd_ops charlcd_tilcd_ops = {
@@ -915,6 +917,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.cursor		= hd44780_common_cursor,
 	.blink		= hd44780_common_blink,
 	.fontsize	= hd44780_common_fontsize,
+	.lines		= hd44780_common_lines,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 23/32] auxdisplay: Remove unnecessary hd44780 from charlcd
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (8 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 22/32] auxdisplay: Implement hd44780_common_lines poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common poeschel
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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

Reviewed-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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_PERIOD	4
 
-/* 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_CHAR		27	/* 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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (9 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 23/32] auxdisplay: Remove unnecessary hd44780 from charlcd poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-16  3:19   ` Miguel Ojeda
  2020-10-05 13:01 ` [PATCH v4 25/32] auxdisplay: Call charlcd_backlight in place poeschel
                   ` (7 subsequent siblings)
  18 siblings, 1 reply; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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_PERIOD	4
 
-#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_CHAR		27	/* 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 : LGcxxxxx...xx; must have <c> between '0'
-		 * and '7', representing the numerical ASCII code of the
-		 * redefined character, and <xx...xx> 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 mode */
@@ -193,6 +194,7 @@ static const struct charlcd_ops hd44780_ops_gpio4 = {
 	.blink		= hd44780_common_blink,
 	.fontsize	= hd44780_common_fontsize,
 	.lines		= hd44780_common_lines,
+	.redefine_char	= hd44780_common_redefine_char,
 };
 
 static int hd44780_probe(struct platform_device *pdev)
diff --git a/drivers/auxdisplay/hd44780_common.c b/drivers/auxdisplay/hd44780_common.c
index 2df2410f3874..82afae78f46e 100644
--- a/drivers/auxdisplay/hd44780_common.c
+++ b/drivers/auxdisplay/hd44780_common.c
@@ -26,6 +26,8 @@
 #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 */
 
 /* sleeps that many milliseconds with a reschedule */
@@ -289,6 +291,67 @@ int hd44780_common_lines(struct charlcd *lcd, enum charlcd_lines lines)
 }
 EXPORT_SYMBOL_GPL(hd44780_common_lines);
 
+int hd44780_common_redefine_char(struct charlcd *lcd, char *esc)
+{
+	/* Generator : LGcxxxxx...xx; must have <c> between '0'
+	 * and '7', representing the numerical ASCII code of the
+	 * redefined character, and <xx...xx> 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.
+	 */
+
+	struct hd44780_common *hdc = lcd->drvdata;
+	unsigned char cgbytes[8];
+	unsigned char cgaddr;
+	int cgoffset;
+	int shift;
+	char value;
+	int addr;
+
+	if (!strchr(esc, ';'))
+		return 0;
+
+	esc++;
+
+	cgaddr = *(esc++) - '0';
+	if (cgaddr > 7)
+		return 1;
+
+	cgoffset = 0;
+	shift = 0;
+	value = 0;
+	while (*esc && cgoffset < 8) {
+		shift ^= 4;
+		if (*esc >= '0' && *esc <= '9') {
+			value |= (*esc - '0') << shift;
+		} else if (*esc >= 'A' && *esc <= 'F') {
+			value |= (*esc - 'A' + 10) << shift;
+		} else if (*esc >= 'a' && *esc <= 'f') {
+			value |= (*esc - 'a' + 10) << shift;
+		} else {
+			esc++;
+			continue;
+		}
+
+		if (shift == 0) {
+			cgbytes[cgoffset++] = value;
+			value = 0;
+		}
+
+		esc++;
+	}
+
+	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);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(hd44780_common_redefine_char);
+
 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 419065bfaea2..d3758230b7fd 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -29,5 +29,6 @@ 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);
+int hd44780_common_redefine_char(struct charlcd *lcd, char *esc);
 struct hd44780_common *hd44780_common_alloc(void);
 
diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c
index 3d33d7cc979c..b0d2ae5b9be8 100644
--- a/drivers/auxdisplay/panel.c
+++ b/drivers/auxdisplay/panel.c
@@ -886,6 +886,7 @@ static const struct charlcd_ops charlcd_serial_ops = {
 	.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 = {
@@ -902,6 +903,7 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 	.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 = {
@@ -918,6 +920,7 @@ static const struct charlcd_ops charlcd_tilcd_ops = {
 	.blink		= hd44780_common_blink,
 	.fontsize	= hd44780_common_fontsize,
 	.lines		= hd44780_common_lines,
+	.redefine_char	= hd44780_common_redefine_char,
 };
 
 /* initialize the LCD driver */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 25/32] auxdisplay: Call charlcd_backlight in place
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (10 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 26/32] auxdisplay: hd44780_common: Reduce clear_display timeout poeschel
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 26/32] auxdisplay: hd44780_common: Reduce clear_display timeout
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (11 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 25/32] auxdisplay: Call charlcd_backlight in place poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 27/32] auxdisplay: hd44780: Remove clear_fast poeschel
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel

From: Lars Poeschel <poeschel@lemonage.de>

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.GG16421@1wt.eu/
Link: https://www.crystalfontz.com/controllers/Hitachi/HD44780/433/

Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 27/32] auxdisplay: hd44780: Remove clear_fast
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (12 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 26/32] auxdisplay: hd44780_common: Reduce clear_display timeout poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 28/32] auxdisplay: charlcd: replace last device specific stuff poeschel
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, Willy Tarreau, Ksenija Stanojevic, open list
  Cc: Lars Poeschel

From: Lars Poeschel <poeschel@lemonage.de>

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.GG16421@1wt.eu/

Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
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-poeschel@lemonage.de/
Link: https://lore.kernel.org/lkml/20200921144645.2061313-28-poeschel@lemonage.de/
Link: https://lore.kernel.org/lkml/20200921144645.2061313-29-poeschel@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(&pprt_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(&pprt_lock);
-	for (pos = 0; pos < charlcd->height * hdc->hwidth; pos++) {
-		lcd_send_serial(0x5F);	/* R/W=W, RS=1 */
-		lcd_send_serial(' ' & 0x0F);
-		lcd_send_serial((' ' >> 4) & 0x0F);
-		/* the shortest data takes at least 40 us */
-		udelay(40);
-	}
-	spin_unlock_irq(&pprt_lock);
-}
-
-/* fills the display with spaces and resets X/Y */
-static void lcd_clear_fast_p8(struct charlcd *charlcd)
-{
-	struct hd44780_common *hdc = charlcd->drvdata;
-	int pos;
-
-	spin_lock_irq(&pprt_lock);
-	for (pos = 0; pos < charlcd->height * hdc->hwidth; pos++) {
-		/* present the data to the data port */
-		w_dtr(pprt, ' ');
-
-		/* maintain the data during 20 us before the strobe */
-		udelay(20);
-
-		set_bit(LCD_BIT_E, bits);
-		set_bit(LCD_BIT_RS, bits);
-		clear_bit(LCD_BIT_RW, bits);
-		set_ctrl_bits();
-
-		/* maintain the strobe during 40 us */
-		udelay(40);
-
-		clear_bit(LCD_BIT_E, bits);
-		set_ctrl_bits();
-
-		/* the shortest data takes at least 45 us */
-		udelay(45);
-	}
-	spin_unlock_irq(&pprt_lock);
-}
-
-/* fills the display with spaces and resets X/Y */
-static void lcd_clear_fast_tilcd(struct charlcd *charlcd)
-{
-	struct hd44780_common *hdc = charlcd->drvdata;
-	int pos;
-
-	spin_lock_irq(&pprt_lock);
-	for (pos = 0; pos < charlcd->height * hdc->hwidth; pos++) {
-		/* present the data to the data port */
-		w_dtr(pprt, ' ');
-		udelay(60);
-	}
-
-	spin_unlock_irq(&pprt_lock);
-}
-
 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,
@@ -890,7 +825,6 @@ static const struct charlcd_ops charlcd_serial_ops = {
 };
 
 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,
@@ -907,7 +841,6 @@ static const struct charlcd_ops charlcd_parallel_ops = {
 };
 
 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,
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 28/32] auxdisplay: charlcd: replace last device specific stuff
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (13 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 27/32] auxdisplay: hd44780: Remove clear_fast poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 29/32] auxdisplay: Change gotoxy calling interface poeschel
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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 <generated/utsrelease.h>
 
 #include "charlcd.h"
-#include "hd44780_common.h"
 
 /* Keep the backlight on this many seconds for each flash */
 #define LCD_BL_TEMPO_PERIOD	4
@@ -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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 29/32] auxdisplay: Change gotoxy calling interface
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (14 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 28/32] auxdisplay: charlcd: replace last device specific stuff poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 30/32] auxdisplay: charlcd: Do not print chars at end of line poeschel
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
 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, &lcd->addr.x, &lcd->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 @@ int hd44780_common_redefine_char(struct charlcd *lcd, char *esc)
 		hdc->write_data(hdc, cgbytes[addr]);
 
 	/* ensures that we stop writing to CGRAM */
-	lcd->ops->gotoxy(lcd);
+	lcd->ops->gotoxy(lcd, lcd->addr.x, lcd->addr.y);
 	return 1;
 }
 EXPORT_SYMBOL_GPL(hd44780_common_redefine_char);
diff --git a/drivers/auxdisplay/hd44780_common.h b/drivers/auxdisplay/hd44780_common.h
index d3758230b7fd..7a7f316d15aa 100644
--- a/drivers/auxdisplay/hd44780_common.h
+++ b/drivers/auxdisplay/hd44780_common.h
@@ -16,7 +16,7 @@ struct hd44780_common {
 };
 
 int hd44780_common_print(struct charlcd *lcd, int c);
-int hd44780_common_gotoxy(struct charlcd *lcd);
+int hd44780_common_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y);
 int hd44780_common_home(struct charlcd *lcd);
 int hd44780_common_clear_display(struct charlcd *lcd);
 int hd44780_common_init_display(struct charlcd *lcd);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 30/32] auxdisplay: charlcd: Do not print chars at end of line
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (15 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 29/32] auxdisplay: Change gotoxy calling interface poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-05 13:01 ` [PATCH v4 31/32] auxdisplay: lcd2s DT binding doc poeschel
  2020-10-05 13:01 ` [PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display poeschel
  18 siblings, 0 replies; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel, Willy Tarreau

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 31/32] auxdisplay: lcd2s DT binding doc
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (16 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 30/32] auxdisplay: charlcd: Do not print chars at end of line poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-06 21:56   ` Rob Herring
  2020-10-05 13:01 ` [PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display poeschel
  18 siblings, 1 reply; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Rob Herring, Lars Poeschel, Willy Tarreau, Sam Ravnborg,
	Linus Walleij, Arnd Bergmann, Mark Brown, Lubomir Rintel,
	Daniel Palmer, Geert Uytterhoeven, allen, Kuninori Morimoto,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list

From: Lars Poeschel <poeschel@lemonage.de>

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 <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
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 000000000000..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 <poeschel@lemonage.de>
+
+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


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display
  2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
                   ` (17 preceding siblings ...)
  2020-10-05 13:01 ` [PATCH v4 31/32] auxdisplay: lcd2s DT binding doc poeschel
@ 2020-10-05 13:01 ` poeschel
  2020-10-16  3:25   ` Miguel Ojeda
  18 siblings, 1 reply; 24+ messages in thread
From: poeschel @ 2020-10-05 13:01 UTC (permalink / raw)
  To: Miguel Ojeda Sandonis, open list; +Cc: Lars Poeschel

From: Lars Poeschel <poeschel@lemonage.de>

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

Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
---
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 000000000000..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 <poeschel@lemonage.de>
+ *  All rights reserved.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+
+#include "charlcd.h"
+
+#define LCD2S_CMD_CUR_MOVES_FWD		0x09
+#define LCD2S_CMD_CUR_BLINK_OFF		0x10
+#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_ON		0x19
+#define LCD2S_CMD_DISPLAY_ON		0x1a
+#define LCD2S_CMD_BACKLIGHT_OFF		0x20
+#define LCD2S_CMD_BACKLIGHT_ON		0x28
+#define LCD2S_CMD_WRITE			0x80
+#define LCD2S_CMD_MOV_CUR_RIGHT		0x83
+#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_RESET		0x8b
+#define LCD2S_CMD_CLEAR			0x8c
+#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] = { LCD2S_CMD_WRITE, c };
+
+	lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
+	return 0;
+}
+
+static int lcd2s_gotoxy(struct charlcd *lcd, unsigned int x, unsigned int y)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+	u8 buf[] = { LCD2S_CMD_CUR_POS, y + 1, x + 1};
+
+	lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
+
+	return 0;
+}
+
+static int lcd2s_home(struct charlcd *lcd)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_RESET);
+	return 0;
+}
+
+static int lcd2s_init_display(struct charlcd *lcd)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	/* turn everything off, but display on */
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_DISPLAY_ON);
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_BACKLIGHT_OFF);
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_MOVES_FWD);
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_BLINK_OFF);
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_UL_OFF);
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CLEAR);
+
+	return 0;
+}
+
+static int lcd2s_shift_cursor(struct charlcd *lcd, enum charlcd_shift_dir dir)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	if (dir == CHARLCD_SHIFT_LEFT)
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_MOV_CUR_LEFT);
+	else
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_MOV_CUR_RIGHT);
+
+	return 0;
+}
+
+static int lcd2s_shift_display(struct charlcd *lcd, enum charlcd_shift_dir dir)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	if (dir == CHARLCD_SHIFT_LEFT)
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_SHIFT_LEFT);
+	else
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_SHIFT_RIGHT);
+
+	return 0;
+}
+
+static void lcd2s_backlight(struct charlcd *lcd, enum charlcd_onoff on)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	if (on)
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_BACKLIGHT_ON);
+	else
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_BACKLIGHT_OFF);
+}
+
+static int lcd2s_display(struct charlcd *lcd, enum charlcd_onoff on)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	if (on)
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_DISPLAY_ON);
+	else
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_DISPLAY_OFF);
+
+	return 0;
+}
+
+static int lcd2s_cursor(struct charlcd *lcd, enum charlcd_onoff on)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	if (on)
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_UL_ON);
+	else
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_UL_OFF);
+
+	return 0;
+}
+
+static int lcd2s_blink(struct charlcd *lcd, enum charlcd_onoff on)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	if (on)
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_BLINK_ON);
+	else
+		lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CUR_BLINK_OFF);
+
+	return 0;
+}
+
+static int lcd2s_fontsize(struct charlcd *lcd, enum charlcd_fontsize size)
+{
+	return 0;
+}
+
+static int lcd2s_lines(struct charlcd *lcd, enum charlcd_lines lines)
+{
+	return 0;
+}
+
+static int lcd2s_redefine_char(struct charlcd *lcd, char *esc)
+{
+	/* Generator : LGcxxxxx...xx; must have <c> between '0'
+	 * and '7', representing the numerical ASCII code of the
+	 * redefined character, and <xx...xx> 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.
+	 */
+
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+	u8 buf[LCD2S_CHARACTER_SIZE + 2] = { LCD2S_CMD_DEF_CUSTOM_CHAR };
+	u8 value;
+	int shift, i;
+
+	if (!strchr(esc, ';'))
+		return 0;
+
+	esc++;
+
+	buf[1] = *(esc++) - '0';
+	if (buf[1] > 7)
+		return 1;
+
+	i = 0;
+	shift = 0;
+	value = 0;
+	while (*esc && i < LCD2S_CHARACTER_SIZE + 2) {
+		shift ^= 4;
+		if (*esc >= '0' && *esc <= '9') {
+			value |= (*esc - '0') << shift;
+		} else if (*esc >= 'A' && *esc <= 'Z') {
+			value |= (*esc - 'A' + 10) << shift;
+		} else if (*esc >= 'a' && *esc <= 'z') {
+			value |= (*esc - 'a' + 10) << shift;
+		} else {
+			esc++;
+			continue;
+		}
+
+		if (shift == 0) {
+			buf[i++] = value;
+			value = 0;
+		}
+
+		esc++;
+	}
+
+	lcd2s_i2c_master_send(lcd2s->i2c, buf, sizeof(buf));
+	return 1;
+}
+
+static int lcd2s_clear_display(struct charlcd *lcd)
+{
+	struct lcd2s_data *lcd2s = lcd->drvdata;
+
+	/* This implicitly sets cursor to first row and column */
+	lcd2s_i2c_smbus_write_byte(lcd2s->i2c, LCD2S_CMD_CLEAR);
+	return 0;
+}
+
+static const struct charlcd_ops lcd2s_ops = {
+	.print		= lcd2s_print,
+	.backlight	= lcd2s_backlight,
+	.gotoxy		= lcd2s_gotoxy,
+	.home		= lcd2s_home,
+	.clear_display	= lcd2s_clear_display,
+	.init_display	= lcd2s_init_display,
+	.shift_cursor	= lcd2s_shift_cursor,
+	.shift_display	= lcd2s_shift_display,
+	.display	= lcd2s_display,
+	.cursor		= lcd2s_cursor,
+	.blink		= lcd2s_blink,
+	.fontsize	= lcd2s_fontsize,
+	.lines		= lcd2s_lines,
+	.redefine_char	= lcd2s_redefine_char,
+};
+
+static int lcd2s_i2c_probe(struct i2c_client *i2c,
+				const struct i2c_device_id *id)
+{
+	struct charlcd *lcd;
+	struct lcd2s_data *lcd2s;
+	int err;
+
+	if (!i2c_check_functionality(i2c->adapter,
+			I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
+			I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
+		return -EIO;
+
+	/* Test, if the display is responding */
+	err = lcd2s_i2c_smbus_write_byte(i2c, LCD2S_CMD_DISPLAY_OFF);
+	if (err < 0)
+		return err;
+
+	lcd = charlcd_alloc();
+	if (!lcd)
+		return -ENOMEM;
+
+	lcd2s = kzalloc(sizeof(struct lcd2s_data), GFP_KERNEL);
+	if (!lcd2s) {
+		err = -ENOMEM;
+		goto fail1;
+	}
+
+	lcd->drvdata = lcd2s;
+	lcd2s->i2c = i2c;
+	lcd2s->charlcd = lcd;
+
+	/* Required properties */
+	err = device_property_read_u32(&i2c->dev, "display-height-chars",
+			&lcd->height);
+	if (err)
+		goto fail2;
+
+	err = device_property_read_u32(&i2c->dev, "display-width-chars",
+			&lcd->width);
+	if (err)
+		goto fail2;
+
+	lcd->ops = &lcd2s_ops;
+
+	err = charlcd_register(lcd2s->charlcd);
+	if (err)
+		goto fail2;
+
+	i2c_set_clientdata(i2c, lcd2s);
+	return 0;
+
+fail2:
+	kfree(lcd2s);
+fail1:
+	kfree(lcd);
+	return err;
+}
+
+static int lcd2s_i2c_remove(struct i2c_client *i2c)
+{
+	struct lcd2s_data *lcd2s = i2c_get_clientdata(i2c);
+
+	kfree(lcd2s->charlcd);
+	charlcd_unregister(lcd2s->charlcd);
+	return 0;
+}
+
+static const struct i2c_device_id lcd2s_i2c_id[] = {
+	{ "lcd2s", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, lcd2s_i2c_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id lcd2s_of_table[] = {
+	{ .compatible = "modtronix,lcd2s" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, lcd2s_of_table);
+#endif
+
+static struct i2c_driver lcd2s_i2c_driver = {
+	.driver = {
+		.name = "lcd2s",
+		.owner = THIS_MODULE,
+#ifdef CONFIG_OF
+		.of_match_table = of_match_ptr(lcd2s_of_table),
+#endif
+	},
+	.probe = lcd2s_i2c_probe,
+	.remove = lcd2s_i2c_remove,
+	.id_table = lcd2s_i2c_id,
+};
+
+static int __init lcd2s_modinit(void)
+{
+	int ret = 0;
+
+	ret = i2c_add_driver(&lcd2s_i2c_driver);
+	if (ret != 0)
+		pr_err("Failed to register lcd2s driver\n");
+
+	return ret;
+}
+module_init(lcd2s_modinit)
+
+static void __exit lcd2s_exit(void)
+{
+	i2c_del_driver(&lcd2s_i2c_driver);
+}
+module_exit(lcd2s_exit)
+
+MODULE_DESCRIPTION("LCD2S character display driver");
+MODULE_AUTHOR("Lars Poeschel");
+MODULE_LICENSE("GPL");
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH v4 31/32] auxdisplay: lcd2s DT binding doc
  2020-10-05 13:01 ` [PATCH v4 31/32] auxdisplay: lcd2s DT binding doc poeschel
@ 2020-10-06 21:56   ` Rob Herring
  0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2020-10-06 21:56 UTC (permalink / raw)
  To: poeschel
  Cc: Rob Herring, Sam Ravnborg, Arnd Bergmann, linux-kernel,
	Linus Walleij, allen, Lubomir Rintel, Kuninori Morimoto,
	Willy Tarreau, Daniel Palmer, devicetree, Geert Uytterhoeven,
	Mark Brown

On Mon, 05 Oct 2020 15:01:27 +0200, poeschel@lemonage.de wrote:
> From: Lars Poeschel <poeschel@lemonage.de>
> 
> 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 <w@1wt.eu>
> Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
> ---
> 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
> 

Reviewed-by: Rob Herring <robh@kernel.org>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common
  2020-10-05 13:01 ` [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common poeschel
@ 2020-10-16  3:16   ` Miguel Ojeda
  0 siblings, 0 replies; 24+ messages in thread
From: Miguel Ojeda @ 2020-10-16  3:16 UTC (permalink / raw)
  To: Lars Poeschel; +Cc: Willy Tarreau, Ksenija Stanojevic, open list, Willy Tarreau

On Mon, Oct 5, 2020 at 3:01 PM <poeschel@lemonage.de> wrote:
>
> 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

it's -> its

(Already corrected in my queue)

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common
  2020-10-05 13:01 ` [PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common poeschel
@ 2020-10-16  3:19   ` Miguel Ojeda
  0 siblings, 0 replies; 24+ messages in thread
From: Miguel Ojeda @ 2020-10-16  3:19 UTC (permalink / raw)
  To: Lars Poeschel; +Cc: Willy Tarreau, Ksenija Stanojevic, open list, Willy Tarreau

On Mon, Oct 5, 2020 at 3:01 PM <poeschel@lemonage.de> wrote:
>
> +       while (*esc && cgoffset < 8) {
> +               shift ^= 4;
> +               if (*esc >= '0' && *esc <= '9') {
> +                       value |= (*esc - '0') << shift;
> +               } else if (*esc >= 'A' && *esc <= 'F') {
> +                       value |= (*esc - 'A' + 10) << shift;
> +               } else if (*esc >= 'a' && *esc <= 'f') {
> +                       value |= (*esc - 'a' + 10) << shift;

I just noticed this is undoing commit 3f03b6498 ("auxdisplay: charlcd:
Reuse hex_to_bin() instead of custom code"). Lars?

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display
  2020-10-05 13:01 ` [PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display poeschel
@ 2020-10-16  3:25   ` Miguel Ojeda
  0 siblings, 0 replies; 24+ messages in thread
From: Miguel Ojeda @ 2020-10-16  3:25 UTC (permalink / raw)
  To: Lars Poeschel; +Cc: open list

On Mon, Oct 5, 2020 at 3:01 PM <poeschel@lemonage.de> wrote:
>
> +       while (*esc && i < LCD2S_CHARACTER_SIZE + 2) {
> +               shift ^= 4;
> +               if (*esc >= '0' && *esc <= '9') {
> +                       value |= (*esc - '0') << shift;
> +               } else if (*esc >= 'A' && *esc <= 'Z') {
> +                       value |= (*esc - 'A' + 10) << shift;
> +               } else if (*esc >= 'a' && *esc <= 'z') {
> +                       value |= (*esc - 'a' + 10) << shift;

This should also probably use hex_to_bin() or similar (see my other
comment on patch 24) and/or share the implementation as much as
possible.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2020-10-16  3:28 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-05 13:01 [PATCH v4 13/32] auxdisplay: Make use of enum for backlight on / off poeschel
2020-10-05 13:01 ` [PATCH v4 14/32] auxdisplay: Move init_display to hd44780_common poeschel
2020-10-16  3:16   ` Miguel Ojeda
2020-10-05 13:01 ` [PATCH v4 15/32] auxdisplay: implement hd44780_common_shift_cursor poeschel
2020-10-05 13:01 ` [PATCH v4 16/32] auxdisplay: Implement hd44780_common_display_shift poeschel
2020-10-05 13:01 ` [PATCH v4 17/32] auxdisplay: Implement a hd44780_common_display poeschel
2020-10-05 13:01 ` [PATCH v4 18/32] auxdisplay: Implement hd44780_common_cursor poeschel
2020-10-05 13:01 ` [PATCH v4 19/32] auxdisplay: Implement hd44780_common_blink poeschel
2020-10-05 13:01 ` [PATCH v4 20/32] auxdisplay: cleanup unnecessary hd44780 code in charlcd poeschel
2020-10-05 13:01 ` [PATCH v4 21/32] auxdisplay: Implement hd44780_common_fontsize poeschel
2020-10-05 13:01 ` [PATCH v4 22/32] auxdisplay: Implement hd44780_common_lines poeschel
2020-10-05 13:01 ` [PATCH v4 23/32] auxdisplay: Remove unnecessary hd44780 from charlcd poeschel
2020-10-05 13:01 ` [PATCH v4 24/32] auxdisplay: Move char redefine code to hd44780_common poeschel
2020-10-16  3:19   ` Miguel Ojeda
2020-10-05 13:01 ` [PATCH v4 25/32] auxdisplay: Call charlcd_backlight in place poeschel
2020-10-05 13:01 ` [PATCH v4 26/32] auxdisplay: hd44780_common: Reduce clear_display timeout poeschel
2020-10-05 13:01 ` [PATCH v4 27/32] auxdisplay: hd44780: Remove clear_fast poeschel
2020-10-05 13:01 ` [PATCH v4 28/32] auxdisplay: charlcd: replace last device specific stuff poeschel
2020-10-05 13:01 ` [PATCH v4 29/32] auxdisplay: Change gotoxy calling interface poeschel
2020-10-05 13:01 ` [PATCH v4 30/32] auxdisplay: charlcd: Do not print chars at end of line poeschel
2020-10-05 13:01 ` [PATCH v4 31/32] auxdisplay: lcd2s DT binding doc poeschel
2020-10-06 21:56   ` Rob Herring
2020-10-05 13:01 ` [PATCH v4 32/32] auxdisplay: add a driver for lcd2s character display poeschel
2020-10-16  3:25   ` Miguel Ojeda

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).