auxdisplay: Move init_display to hd44780_common
authorLars Poeschel <poeschel@lemonage.de>
Tue, 3 Nov 2020 09:58:17 +0000 (10:58 +0100)
committerMiguel Ojeda <ojeda@kernel.org>
Wed, 4 Nov 2020 10:04:04 +0000 (11:04 +0100)
The init_display function is moved over to hd44780_common. charlcd uses
it via its ops function pointer and drivers initialize the ops with the
common hd44780_common_init_display function.

Reviewed-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
drivers/auxdisplay/charlcd.c
drivers/auxdisplay/charlcd.h
drivers/auxdisplay/hd44780.c
drivers/auxdisplay/hd44780_common.c
drivers/auxdisplay/hd44780_common.h
drivers/auxdisplay/panel.c

index 9631f70..94f6b0a 100644 (file)
@@ -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>
 /* 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;
 
index a321030..dd40fd8 100644 (file)
@@ -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,
@@ -46,6 +53,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);
@@ -54,6 +62,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);
index 40ea6d2..5916da0 100644 (file)
@@ -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)
index 2f7d556..7d4aea3 100644 (file)
@@ -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;
index ef11935..a8e3228 100644 (file)
@@ -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,4 +19,5 @@ 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);
index 8adf627..583bd22 100644 (file)
@@ -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 */