]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
video console: refactoring and optimization
authorDzmitry Sankouski <dsankouski@gmail.com>
Tue, 7 Mar 2023 10:21:11 +0000 (13:21 +0300)
committerAnatolij Gustschin <agust@denx.de>
Tue, 7 Mar 2023 12:26:08 +0000 (13:26 +0100)
- move common code to vidconsole_internal.h and console_core.c
- unite probe functions
- get rid of code duplications in switch across bpp values
- extract common pixel fill logic in two functions one per
horizontal and vertical filling
- rearrange statements in put_xy* methods in unified way
- replace types - uint*_t to u*

Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/video/Makefile
drivers/video/console_core.c [new file with mode: 0644]
drivers/video/console_normal.c
drivers/video/console_rotate.c
drivers/video/vidconsole_internal.h [new file with mode: 0644]
include/video_console.h

index cdb7d9a54d4b5622d93bafcc448532aacf91cdcc..cb3f3736459b55266d8055dbca6f8aca01dec409 100644 (file)
@@ -9,6 +9,12 @@ obj-$(CONFIG_BACKLIGHT_GPIO) += backlight_gpio.o
 obj-$(CONFIG_BACKLIGHT_PWM) += pwm_backlight.o
 obj-$(CONFIG_CONSOLE_NORMAL) += console_normal.o
 obj-$(CONFIG_CONSOLE_ROTATION) += console_rotate.o
+ifdef CONFIG_CONSOLE_NORMAL
+obj-y += console_core.o
+else ifdef CONFIG_CONSOLE_ROTATION
+obj-y += console_core.o
+endif
+obj-$(CONFIG_CONSOLE_ROTATION) += console_core.o
 obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/
 obj-$(CONFIG_DISPLAY) += display-uclass.o
 obj-$(CONFIG_VIDEO_MIPI_DSI) += dsi-host-uclass.o
diff --git a/drivers/video/console_core.c b/drivers/video/console_core.c
new file mode 100644 (file)
index 0000000..9c2e4cb
--- /dev/null
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2015
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+#include <video.h>
+#include <video_console.h>
+#include <dm.h>
+#include "vidconsole_internal.h"
+
+int check_bpix_support(int bpix)
+{
+       if (bpix == VIDEO_BPP8 && IS_ENABLED(CONFIG_VIDEO_BPP8))
+               return 0;
+       else if (bpix == VIDEO_BPP16 && IS_ENABLED(CONFIG_VIDEO_BPP16))
+               return 0;
+       else if (bpix == VIDEO_BPP32 && IS_ENABLED(CONFIG_VIDEO_BPP32))
+               return 0;
+       else
+               return -ENOSYS;
+}
+
+inline void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step)
+{
+       u8 *dst_byte = *dstp;
+
+       if (pbytes == 4) {
+               u32 *dst = *dstp;
+               *dst = value;
+       }
+       if (pbytes == 2) {
+               u16 *dst = *dstp;
+               *dst = value;
+       }
+       if (pbytes == 1) {
+               u8 *dst = *dstp;
+               *dst = value;
+       }
+       *dstp = dst_byte + step;
+}
+
+int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv,
+                        bool direction)
+{
+       int step, line_step, pbytes, ret;
+       void *dst;
+
+       ret = check_bpix_support(vid_priv->bpix);
+       if (ret)
+               return ret;
+
+       pbytes = VNBYTES(vid_priv->bpix);
+       if (direction) {
+               step = -pbytes;
+               line_step = -vid_priv->line_length;
+       } else {
+               step = pbytes;
+               line_step = vid_priv->line_length;
+       }
+
+       for (int row = 0; row < VIDEO_FONT_HEIGHT; row++) {
+               dst = *line;
+               uchar bits = pfont[row];
+
+               for (int i = 0; i < VIDEO_FONT_WIDTH; i++) {
+                       u32 value = (bits & 0x80) ?
+                               vid_priv->colour_fg :
+                               vid_priv->colour_bg;
+
+                       fill_pixel_and_goto_next(&dst,
+                                                value,
+                                                pbytes,
+                                                step
+                       );
+                       bits <<= 1;
+               }
+               *line += line_step;
+       }
+       return ret;
+}
+
+int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv,
+                          bool direction)
+{
+       int step, line_step, pbytes, ret;
+       void *dst;
+       u8 mask = 0x80;
+
+       ret = check_bpix_support(vid_priv->bpix);
+       if (ret)
+               return ret;
+
+       pbytes = VNBYTES(vid_priv->bpix);
+       if (direction) {
+               step = -pbytes;
+               line_step = vid_priv->line_length;
+       } else {
+               step = pbytes;
+               line_step = -vid_priv->line_length;
+       }
+       for (int col = 0; col < VIDEO_FONT_WIDTH; col++) {
+               dst = *line;
+               for (int row = 0; row < VIDEO_FONT_HEIGHT; row++) {
+                       u32 value = (pfont[row * VIDEO_FONT_BYTE_WIDTH] & mask) ?
+                                               vid_priv->colour_fg :
+                                               vid_priv->colour_bg;
+
+                       fill_pixel_and_goto_next(&dst,
+                                                value,
+                                                pbytes,
+                                                step
+                       );
+               }
+               *line += line_step;
+               mask >>= 1;
+       }
+       return ret;
+}
+
+int console_probe(struct udevice *dev)
+{
+       struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
+       struct udevice *vid_dev = dev->parent;
+       struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
+
+       vc_priv->x_charsize = VIDEO_FONT_WIDTH;
+       vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
+       if (vid_priv->rot % 2) {
+               vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
+               vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
+               vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
+       } else {
+               vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
+               vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
+       }
+
+       return 0;
+}
index 04f022491e52db6eb29b2d716670e675fc61294c..57186bedd86b8fbe36fb72b0d9fbeac0ab2dec58 100644 (file)
@@ -1,10 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (c) 2015 Google, Inc
- * (C) Copyright 2001-2015
- * DENX Software Engineering -- wd@denx.de
- * Compulab Ltd - http://compulab.co.il/
+ * (C) Copyright 2015
  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
  */
 
 #include <common.h>
 #include <video.h>
 #include <video_console.h>
 #include <video_font.h>                /* Get font data, width and height */
+#include "vidconsole_internal.h"
 
-static int console_normal_set_row(struct udevice *dev, uint row, int clr)
+static int console_set_row(struct udevice *dev, uint row, int clr)
 {
        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
-       void *line, *end;
+       void *line, *dst, *end;
        int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
        int ret;
        int i;
+       int pbytes;
+
+       ret = check_bpix_support(vid_priv->bpix);
+       if (ret)
+               return ret;
 
        line = vid_priv->fb + row * VIDEO_FONT_HEIGHT * vid_priv->line_length;
-       switch (vid_priv->bpix) {
-       case VIDEO_BPP8:
-               if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                       uint8_t *dst = line;
-
-                       for (i = 0; i < pixels; i++)
-                               *dst++ = clr;
-                       end = dst;
-                       break;
-               }
-       case VIDEO_BPP16:
-               if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                       uint16_t *dst = line;
-
-                       for (i = 0; i < pixels; i++)
-                               *dst++ = clr;
-                       end = dst;
-                       break;
-               }
-       case VIDEO_BPP32:
-               if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                       uint32_t *dst = line;
-
-                       for (i = 0; i < pixels; i++)
-                               *dst++ = clr;
-                       end = dst;
-                       break;
-               }
-       default:
-               return -ENOSYS;
-       }
+       dst = line;
+       pbytes = VNBYTES(vid_priv->bpix);
+       for (i = 0; i < pixels; i++)
+               fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
+       end = dst;
+
        ret = vidconsole_sync_copy(dev, line, end);
        if (ret)
                return ret;
@@ -60,8 +40,8 @@ static int console_normal_set_row(struct udevice *dev, uint row, int clr)
        return 0;
 }
 
-static int console_normal_move_rows(struct udevice *dev, uint rowdst,
-                                    uint rowsrc, uint count)
+static int console_move_rows(struct udevice *dev, uint rowdst,
+                            uint rowsrc, uint count)
 {
        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
        void *dst;
@@ -79,70 +59,30 @@ static int console_normal_move_rows(struct udevice *dev, uint rowdst,
        return 0;
 }
 
-static int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y,
-                                 char ch)
+static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, char ch)
 {
        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
        struct udevice *vid = dev->parent;
        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
-       int i, row;
-       void *start;
-       void *line;
-       int ret;
+       int pbytes = VNBYTES(vid_priv->bpix);
+       int x, linenum, ret;
+       void *start, *line;
+       uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 
-       start = vid_priv->fb + y * vid_priv->line_length +
-               VID_TO_PIXEL(x_frac) * VNBYTES(vid_priv->bpix);
+       if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
+               return -EAGAIN;
+       linenum = y;
+       x = VID_TO_PIXEL(x_frac);
+       start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
        line = start;
 
        if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
                return -EAGAIN;
 
-       for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
-               unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
-               uchar bits = video_fontdata[idx];
-
-               switch (vid_priv->bpix) {
-               case VIDEO_BPP8:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                               uint8_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
-                                       *dst++ = (bits & 0x80) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                                       bits <<= 1;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP16:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                               uint16_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
-                                       *dst++ = (bits & 0x80) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                                       bits <<= 1;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP32:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                               uint32_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
-                                       *dst++ = (bits & 0x80) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                                       bits <<= 1;
-                               }
-                               break;
-                       }
-               default:
-                       return -ENOSYS;
-               }
-               line += vid_priv->line_length;
-       }
+       ret = fill_char_vertically(pfont, &line, vid_priv, NORMAL_DIRECTION);
+       if (ret)
+               return ret;
+
        ret = vidconsole_sync_copy(dev, start, line);
        if (ret)
                return ret;
@@ -150,29 +90,15 @@ static int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y,
        return VID_TO_POS(VIDEO_FONT_WIDTH);
 }
 
-static int console_normal_probe(struct udevice *dev)
-{
-       struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
-       struct udevice *vid_dev = dev->parent;
-       struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
-
-       vc_priv->x_charsize = VIDEO_FONT_WIDTH;
-       vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
-       vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
-       vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
-
-       return 0;
-}
-
-struct vidconsole_ops console_normal_ops = {
-       .putc_xy        = console_normal_putc_xy,
-       .move_rows      = console_normal_move_rows,
-       .set_row        = console_normal_set_row,
+struct vidconsole_ops console_ops = {
+       .putc_xy        = console_putc_xy,
+       .move_rows      = console_move_rows,
+       .set_row        = console_set_row,
 };
 
 U_BOOT_DRIVER(vidconsole_normal) = {
        .name   = "vidconsole0",
        .id     = UCLASS_VIDEO_CONSOLE,
-       .ops    = &console_normal_ops,
-       .probe  = console_normal_probe,
+       .ops    = &console_ops,
+       .probe  = console_probe,
 };
index 36c8d0609d8734682d870ce683a987d02e370856..70cc62d1781ab58126682ee7d36c773101dc3f17 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright (c) 2015 Google, Inc
  * (C) Copyright 2015
  * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
  */
 
 #include <common.h>
 #include <video.h>
 #include <video_console.h>
 #include <video_font.h>                /* Get font data, width and height */
+#include "vidconsole_internal.h"
 
 static int console_set_row_1(struct udevice *dev, uint row, int clr)
 {
        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
        int pbytes = VNBYTES(vid_priv->bpix);
-       void *start, *line;
+       void *start, *dst, *line;
        int i, j;
        int ret;
 
@@ -23,34 +25,9 @@ static int console_set_row_1(struct udevice *dev, uint row, int clr)
                (row + 1) * VIDEO_FONT_HEIGHT * pbytes;
        line = start;
        for (j = 0; j < vid_priv->ysize; j++) {
-               switch (vid_priv->bpix) {
-               case VIDEO_BPP8:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                               uint8_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
-                                       *dst++ = clr;
-                               break;
-                       }
-               case VIDEO_BPP16:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                               uint16_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
-                                       *dst++ = clr;
-                               break;
-                       }
-               case VIDEO_BPP32:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                               uint32_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
-                                       *dst++ = clr;
-                               break;
-                       }
-               default:
-                       return -ENOSYS;
-               }
+               dst = line;
+               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+                       fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
                line += vid_priv->line_length;
        }
        ret = vidconsole_sync_copy(dev, start, line);
@@ -61,7 +38,7 @@ static int console_set_row_1(struct udevice *dev, uint row, int clr)
 }
 
 static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
-                              uint count)
+                                  uint count)
 {
        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
        int pbytes = VNBYTES(vid_priv->bpix);
@@ -76,7 +53,7 @@ static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
 
        for (j = 0; j < vid_priv->ysize; j++) {
                ret = vidconsole_memmove(dev, dst, src,
-                                        VIDEO_FONT_HEIGHT * pbytes * count);
+                                       VIDEO_FONT_HEIGHT * pbytes * count);
                if (ret)
                        return ret;
                src += vid_priv->line_length;
@@ -91,60 +68,22 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
        struct udevice *vid = dev->parent;
        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
-       uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
        int pbytes = VNBYTES(vid_priv->bpix);
-       int i, col, x, linenum, ret;
-       int mask = 0x80;
+       int x, linenum, ret;
        void *start, *line;
+       uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 
+       if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
+               return -EAGAIN;
        linenum = VID_TO_PIXEL(x_frac) + 1;
        x = y + 1;
        start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
        line = start;
-       if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
-               return -EAGAIN;
 
-       for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
-               switch (vid_priv->bpix) {
-               case VIDEO_BPP8:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                               uint8_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-                                       *dst-- = (pfont[i] & mask) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP16:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                               uint16_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-                                       *dst-- = (pfont[i] & mask) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP32:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                               uint32_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-                                       *dst-- = (pfont[i] & mask) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                               }
-                               break;
-                       }
-               default:
-                       return -ENOSYS;
-               }
-               line += vid_priv->line_length;
-               mask >>= 1;
-       }
+       ret = fill_char_horizontally(pfont, &line, vid_priv, FLIPPED_DIRECTION);
+       if (ret)
+               return ret;
+
        /* We draw backwards from 'start, so account for the first line */
        ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
        if (ret)
@@ -157,44 +96,18 @@ static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
 static int console_set_row_2(struct udevice *dev, uint row, int clr)
 {
        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
-       void *start, *line, *end;
+       void *start, *line, *dst, *end;
        int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
        int i, ret;
+       int pbytes = VNBYTES(vid_priv->bpix);
 
        start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
                (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
        line = start;
-       switch (vid_priv->bpix) {
-       case VIDEO_BPP8:
-               if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                       uint8_t *dst = line;
-
-                       for (i = 0; i < pixels; i++)
-                               *dst++ = clr;
-                       end = dst;
-                       break;
-               }
-       case VIDEO_BPP16:
-               if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                       uint16_t *dst = line;
-
-                       for (i = 0; i < pixels; i++)
-                               *dst++ = clr;
-                       end = dst;
-                       break;
-               }
-       case VIDEO_BPP32:
-               if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                       uint32_t *dst = line;
-
-                       for (i = 0; i < pixels; i++)
-                               *dst++ = clr;
-                       end = dst;
-                       break;
-               }
-       default:
-               return -ENOSYS;
-       }
+       dst = line;
+       for (i = 0; i < pixels; i++)
+               fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
+       end = dst;
        ret = vidconsole_sync_copy(dev, start, end);
        if (ret)
                return ret;
@@ -227,8 +140,9 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
        struct udevice *vid = dev->parent;
        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
        int pbytes = VNBYTES(vid_priv->bpix);
-       int i, row, x, linenum, ret;
+       int linenum, x, ret;
        void *start, *line;
+       uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 
        if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
                return -EAGAIN;
@@ -237,52 +151,10 @@ static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
        start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
        line = start;
 
-       for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
-               unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
-               uchar bits = video_fontdata[idx];
-
-               switch (vid_priv->bpix) {
-               case VIDEO_BPP8:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                               uint8_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
-                                       *dst-- = (bits & 0x80) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                                       bits <<= 1;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP16:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                               uint16_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
-                                       *dst-- = (bits & 0x80) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                                       bits <<= 1;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP32:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                               uint32_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
-                                       *dst-- = (bits & 0x80) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                                       bits <<= 1;
-                               }
-                               break;
-                       }
-               default:
-                       return -ENOSYS;
-               }
-               line -= vid_priv->line_length;
-       }
+       ret = fill_char_vertically(pfont, &line, vid_priv, FLIPPED_DIRECTION);
+       if (ret)
+               return ret;
+
        /* Add 4 bytes to allow for the first pixel writen */
        ret = vidconsole_sync_copy(dev, start + 4, line);
        if (ret)
@@ -295,40 +167,15 @@ static int console_set_row_3(struct udevice *dev, uint row, int clr)
 {
        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
        int pbytes = VNBYTES(vid_priv->bpix);
-       void *start, *line;
+       void *start, *dst, *line;
        int i, j, ret;
 
        start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
        line = start;
        for (j = 0; j < vid_priv->ysize; j++) {
-               switch (vid_priv->bpix) {
-               case VIDEO_BPP8:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                               uint8_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
-                                       *dst++ = clr;
-                               break;
-                       }
-               case VIDEO_BPP16:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                               uint16_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
-                                       *dst++ = clr;
-                               break;
-                       }
-               case VIDEO_BPP32:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                               uint32_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
-                                       *dst++ = clr;
-                               break;
-                       }
-               default:
-                       return -ENOSYS;
-               }
+               dst = line;
+               for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
+                       fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes);
                line += vid_priv->line_length;
        }
        ret = vidconsole_sync_copy(dev, start, line);
@@ -367,58 +214,21 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
        struct udevice *vid = dev->parent;
        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
-       uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
        int pbytes = VNBYTES(vid_priv->bpix);
-       int i, col, x, ret;
-       int mask = 0x80;
+       int linenum, x, ret;
        void *start, *line;
+       uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 
        if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
                return -EAGAIN;
-       x = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
-       start = vid_priv->fb + x * vid_priv->line_length + y * pbytes;
+       x = y;
+       linenum = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
+       start = vid_priv->fb + linenum * vid_priv->line_length + y * pbytes;
        line = start;
-       for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
-               switch (vid_priv->bpix) {
-               case VIDEO_BPP8:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
-                               uint8_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-                                       *dst++ = (pfont[i] & mask) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP16:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
-                               uint16_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-                                       *dst++ = (pfont[i] & mask) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                               }
-                               break;
-                       }
-               case VIDEO_BPP32:
-                       if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
-                               uint32_t *dst = line;
-
-                               for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
-                                       *dst++ = (pfont[i] & mask) ?
-                                               vid_priv->colour_fg :
-                                               vid_priv->colour_bg;
-                               }
-                               break;
-                       }
-               default:
-                       return -ENOSYS;
-               }
-               line -= vid_priv->line_length;
-               mask >>= 1;
-       }
+
+       ret = fill_char_horizontally(pfont, &line, vid_priv, NORMAL_DIRECTION);
+       if (ret)
+               return ret;
        /* Add a line to allow for the first pixels writen */
        ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
        if (ret)
@@ -427,36 +237,6 @@ static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
        return VID_TO_POS(VIDEO_FONT_WIDTH);
 }
 
-
-static int console_probe_2(struct udevice *dev)
-{
-       struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
-       struct udevice *vid_dev = dev->parent;
-       struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
-
-       vc_priv->x_charsize = VIDEO_FONT_WIDTH;
-       vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
-       vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
-       vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
-
-       return 0;
-}
-
-static int console_probe_1_3(struct udevice *dev)
-{
-       struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
-       struct udevice *vid_dev = dev->parent;
-       struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
-
-       vc_priv->x_charsize = VIDEO_FONT_WIDTH;
-       vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
-       vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
-       vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
-       vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
-
-       return 0;
-}
-
 struct vidconsole_ops console_ops_1 = {
        .putc_xy        = console_putc_xy_1,
        .move_rows      = console_move_rows_1,
@@ -479,19 +259,19 @@ U_BOOT_DRIVER(vidconsole_1) = {
        .name   = "vidconsole1",
        .id     = UCLASS_VIDEO_CONSOLE,
        .ops    = &console_ops_1,
-       .probe  = console_probe_1_3,
+       .probe  = console_probe,
 };
 
 U_BOOT_DRIVER(vidconsole_2) = {
        .name   = "vidconsole2",
        .id     = UCLASS_VIDEO_CONSOLE,
        .ops    = &console_ops_2,
-       .probe  = console_probe_2,
+       .probe  = console_probe,
 };
 
 U_BOOT_DRIVER(vidconsole_3) = {
        .name   = "vidconsole3",
        .id     = UCLASS_VIDEO_CONSOLE,
        .ops    = &console_ops_3,
-       .probe  = console_probe_1_3,
+       .probe  = console_probe,
 };
diff --git a/drivers/video/vidconsole_internal.h b/drivers/video/vidconsole_internal.h
new file mode 100644 (file)
index 0000000..0dfcd40
--- /dev/null
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2015 Google, Inc
+ * (C) Copyright 2015
+ * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
+ * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+#include <video_font.h>                /* Get font data, width and height */
+
+#define VIDEO_FONT_BYTE_WIDTH  ((VIDEO_FONT_WIDTH / 8) + (VIDEO_FONT_WIDTH % 8 > 0))
+
+#define FLIPPED_DIRECTION 1
+#define NORMAL_DIRECTION 0
+
+/**
+ * Checks if bits per pixel supported.
+ *
+ * @param bpix framebuffer bits per pixel.
+ *
+ * @returns 0, if supported, or else -ENOSYS.
+ */
+int check_bpix_support(int bpix);
+
+/**
+ * Fill 1 pixel in framebuffer, and go to next one.
+ *
+ * @param dstp         a pointer to pointer to framebuffer.
+ * @param value                value to write to framebuffer.
+ * @param pbytes       framebuffer bytes per pixel.
+ * @param step         framebuffer pointer increment. Usually is equal to pbytes,
+ *                     and may be negative to control filling direction.
+ */
+void fill_pixel_and_goto_next(void **dstp, u32 value, int pbytes, int step);
+
+/**
+ * Fills 1 character in framebuffer vertically. Vertically means we're filling char font data rows
+ * across the lines.
+ *
+ * @param pfont                a pointer to character font data.
+ * @param line         a pointer to pointer to framebuffer. It's a point for upper left char corner
+ * @param vid_priv     driver private data.
+ * @param direction    controls character orientation. Can be normal or flipped.
+ * When normal:               When flipped:
+ *|-----------------------------------------------|
+ *| line stepping        |                        |
+ *|            |         |       stepping ->      |
+ *|     *      |         |       * * *            |
+ *|   * *      v         |         *              |
+ *|     *                |         *              |
+ *|     *                |         * *      ^     |
+ *|   * * *              |         *        |     |
+ *|                      |                  |     |
+ *| stepping ->          |         line stepping  |
+ *|---!!we're starting from upper left char corner|
+ *|-----------------------------------------------|
+ *
+ * @returns 0, if success, or else error code.
+ */
+int fill_char_vertically(uchar *pfont, void **line, struct video_priv *vid_priv,
+                        bool direction);
+
+/**
+ * Fills 1 character in framebuffer horizontally.
+ * Horizontally means we're filling char font data columns across the lines.
+ *
+ * @param pfont                a pointer to character font data.
+ * @param line         a pointer to pointer to framebuffer. It's a point for upper left char corner
+ * @param vid_priv     driver private data.
+ * @param direction    controls character orientation. Can be normal or flipped.
+ * When normal:               When flipped:
+ *|-----------------------------------------------|
+ *|               *        |   line stepping      |
+ *|    ^  * * * * *        |   |                  |
+ *|    |    *     *        |   v   *     *        |
+ *|    |                   |       * * * * *      |
+ *|  line stepping         |       *              |
+ *|                        |                      |
+ *|  stepping ->           |        <- stepping   |
+ *|---!!we're starting from upper left char corner|
+ *|-----------------------------------------------|
+ *
+ * @returns 0, if success, or else error code.
+ */
+int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv,
+                          bool direction);
+
+/**
+ * console probe function.
+ *
+ * @param dev  a pointer to device.
+ *
+ * @returns 0, if success, or else error code.
+ */
+int console_probe(struct udevice *dev);
index 9d2c0f210e4bcc3589176877dfc04cb1a84967b1..3e1e00c23f930ef311f89b12e4e821f22e6ec483 100644 (file)
@@ -340,6 +340,9 @@ int vidconsole_sync_copy(struct udevice *dev, void *from, void *to);
 int vidconsole_memmove(struct udevice *dev, void *dst, const void *src,
                       int size);
 #else
+
+#include <string.h>
+
 static inline int vidconsole_sync_copy(struct udevice *dev, void *from,
                                       void *to)
 {