auxdisplay: charlcd: Add support for displays with more than two lines
authorGeert Uytterhoeven <geert@linux-m68k.org>
Fri, 10 Mar 2017 14:15:19 +0000 (15:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Mar 2017 06:10:49 +0000 (15:10 +0900)
On displays with more than two lines, the additional lines are stored in
the buffers used for the first two lines, but beyond the visible parts.
Adjust the DDRAM address calculation to cater for this.

When clearing the display, avoid writing more spaces than the actual
size of the physical buffer.

Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/auxdisplay/charlcd.c

index b3a84e90a268478c91d3dd6bef2295e5aec9580f..cfeb049a01ef84425672682c50acb492cbfb04eb 100644 (file)
@@ -159,15 +159,19 @@ EXPORT_SYMBOL_GPL(charlcd_poke);
 static void charlcd_gotoxy(struct charlcd *lcd)
 {
        struct charlcd_priv *priv = to_priv(lcd);
+       unsigned int addr;
 
-       lcd->ops->write_cmd(lcd,
-               LCD_CMD_SET_DDRAM_ADDR | (priv->addr.y ? lcd->hwidth : 0) |
-               /*
-                * we force the cursor to stay at the end of the
-                * line if it wants to go farther
-                */
-               ((priv->addr.x < lcd->bwidth) ? priv->addr.x & (lcd->hwidth - 1)
-                                             : lcd->bwidth - 1));
+       /*
+        * we force the cursor to stay at the end of the
+        * line if it wants to go farther
+        */
+       addr = priv->addr.x < lcd->bwidth ? priv->addr.x & (lcd->hwidth - 1)
+                                         : lcd->bwidth - 1;
+       if (priv->addr.y & 1)
+               addr += lcd->hwidth;
+       if (priv->addr.y & 2)
+               addr += lcd->bwidth;
+       lcd->ops->write_cmd(lcd, LCD_CMD_SET_DDRAM_ADDR | addr);
 }
 
 static void charlcd_home(struct charlcd *lcd)
@@ -203,7 +207,7 @@ static void charlcd_clear_fast(struct charlcd *lcd)
        if (lcd->ops->clear_fast)
                lcd->ops->clear_fast(lcd);
        else
-               for (pos = 0; pos < lcd->height * lcd->hwidth; pos++)
+               for (pos = 0; pos < min(2, lcd->height) * lcd->hwidth; pos++)
                        lcd->ops->write_data(lcd, ' ');
 
        charlcd_home(lcd);