uboot/drivers/video/console_rotate.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Google, Inc
   4 * (C) Copyright 2015
   5 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <video.h>
  11#include <video_console.h>
  12#include <video_font.h>         /* Get font data, width and height */
  13
  14static int console_set_row_1(struct udevice *dev, uint row, int clr)
  15{
  16        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  17        int pbytes = VNBYTES(vid_priv->bpix);
  18        void *start, *line;
  19        int i, j;
  20        int ret;
  21
  22        start = vid_priv->fb + vid_priv->line_length -
  23                (row + 1) * VIDEO_FONT_HEIGHT * pbytes;
  24        line = start;
  25        for (j = 0; j < vid_priv->ysize; j++) {
  26                switch (vid_priv->bpix) {
  27                case VIDEO_BPP8:
  28                        if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
  29                                uint8_t *dst = line;
  30
  31                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  32                                        *dst++ = clr;
  33                                break;
  34                        }
  35                case VIDEO_BPP16:
  36                        if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
  37                                uint16_t *dst = line;
  38
  39                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  40                                        *dst++ = clr;
  41                                break;
  42                        }
  43                case VIDEO_BPP32:
  44                        if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
  45                                uint32_t *dst = line;
  46
  47                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
  48                                        *dst++ = clr;
  49                                break;
  50                        }
  51                default:
  52                        return -ENOSYS;
  53                }
  54                line += vid_priv->line_length;
  55        }
  56        ret = vidconsole_sync_copy(dev, start, line);
  57        if (ret)
  58                return ret;
  59
  60        return 0;
  61}
  62
  63static int console_move_rows_1(struct udevice *dev, uint rowdst, uint rowsrc,
  64                               uint count)
  65{
  66        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
  67        int pbytes = VNBYTES(vid_priv->bpix);
  68        void *dst;
  69        void *src;
  70        int j, ret;
  71
  72        dst = vid_priv->fb + vid_priv->line_length -
  73                (rowdst + count) * VIDEO_FONT_HEIGHT * pbytes;
  74        src = vid_priv->fb + vid_priv->line_length -
  75                (rowsrc + count) * VIDEO_FONT_HEIGHT * pbytes;
  76
  77        for (j = 0; j < vid_priv->ysize; j++) {
  78                ret = vidconsole_memmove(dev, dst, src,
  79                                         VIDEO_FONT_HEIGHT * pbytes * count);
  80                if (ret)
  81                        return ret;
  82                src += vid_priv->line_length;
  83                dst += vid_priv->line_length;
  84        }
  85
  86        return 0;
  87}
  88
  89static int console_putc_xy_1(struct udevice *dev, uint x_frac, uint y, char ch)
  90{
  91        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
  92        struct udevice *vid = dev->parent;
  93        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
  94        uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
  95        int pbytes = VNBYTES(vid_priv->bpix);
  96        int i, col, x, linenum, ret;
  97        int mask = 0x80;
  98        void *start, *line;
  99
 100        linenum = VID_TO_PIXEL(x_frac) + 1;
 101        x = y + 1;
 102        start = vid_priv->fb + linenum * vid_priv->line_length - x * pbytes;
 103        line = start;
 104        if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
 105                return -EAGAIN;
 106
 107        for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
 108                switch (vid_priv->bpix) {
 109                case VIDEO_BPP8:
 110                        if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
 111                                uint8_t *dst = line;
 112
 113                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
 114                                        *dst-- = (pfont[i] & mask) ?
 115                                                vid_priv->colour_fg :
 116                                                vid_priv->colour_bg;
 117                                }
 118                                break;
 119                        }
 120                case VIDEO_BPP16:
 121                        if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
 122                                uint16_t *dst = line;
 123
 124                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
 125                                        *dst-- = (pfont[i] & mask) ?
 126                                                vid_priv->colour_fg :
 127                                                vid_priv->colour_bg;
 128                                }
 129                                break;
 130                        }
 131                case VIDEO_BPP32:
 132                        if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
 133                                uint32_t *dst = line;
 134
 135                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
 136                                        *dst-- = (pfont[i] & mask) ?
 137                                                vid_priv->colour_fg :
 138                                                vid_priv->colour_bg;
 139                                }
 140                                break;
 141                        }
 142                default:
 143                        return -ENOSYS;
 144                }
 145                line += vid_priv->line_length;
 146                mask >>= 1;
 147        }
 148        /* We draw backwards from 'start, so account for the first line */
 149        ret = vidconsole_sync_copy(dev, start - vid_priv->line_length, line);
 150        if (ret)
 151                return ret;
 152
 153        return VID_TO_POS(VIDEO_FONT_WIDTH);
 154}
 155
 156
 157static int console_set_row_2(struct udevice *dev, uint row, int clr)
 158{
 159        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 160        void *start, *line, *end;
 161        int pixels = VIDEO_FONT_HEIGHT * vid_priv->xsize;
 162        int i, ret;
 163
 164        start = vid_priv->fb + vid_priv->ysize * vid_priv->line_length -
 165                (row + 1) * VIDEO_FONT_HEIGHT * vid_priv->line_length;
 166        line = start;
 167        switch (vid_priv->bpix) {
 168        case VIDEO_BPP8:
 169                if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
 170                        uint8_t *dst = line;
 171
 172                        for (i = 0; i < pixels; i++)
 173                                *dst++ = clr;
 174                        end = dst;
 175                        break;
 176                }
 177        case VIDEO_BPP16:
 178                if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
 179                        uint16_t *dst = line;
 180
 181                        for (i = 0; i < pixels; i++)
 182                                *dst++ = clr;
 183                        end = dst;
 184                        break;
 185                }
 186        case VIDEO_BPP32:
 187                if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
 188                        uint32_t *dst = line;
 189
 190                        for (i = 0; i < pixels; i++)
 191                                *dst++ = clr;
 192                        end = dst;
 193                        break;
 194                }
 195        default:
 196                return -ENOSYS;
 197        }
 198        ret = vidconsole_sync_copy(dev, start, end);
 199        if (ret)
 200                return ret;
 201
 202        return 0;
 203}
 204
 205static int console_move_rows_2(struct udevice *dev, uint rowdst, uint rowsrc,
 206                               uint count)
 207{
 208        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 209        void *dst;
 210        void *src;
 211        void *end;
 212
 213        end = vid_priv->fb + vid_priv->ysize * vid_priv->line_length;
 214        dst = end - (rowdst + count) * VIDEO_FONT_HEIGHT *
 215                vid_priv->line_length;
 216        src = end - (rowsrc + count) * VIDEO_FONT_HEIGHT *
 217                vid_priv->line_length;
 218        vidconsole_memmove(dev, dst, src,
 219                           VIDEO_FONT_HEIGHT * vid_priv->line_length * count);
 220
 221        return 0;
 222}
 223
 224static int console_putc_xy_2(struct udevice *dev, uint x_frac, uint y, char ch)
 225{
 226        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
 227        struct udevice *vid = dev->parent;
 228        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
 229        int pbytes = VNBYTES(vid_priv->bpix);
 230        int i, row, x, linenum, ret;
 231        void *start, *line;
 232
 233        if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
 234                return -EAGAIN;
 235        linenum = vid_priv->ysize - y - 1;
 236        x = vid_priv->xsize - VID_TO_PIXEL(x_frac) - 1;
 237        start = vid_priv->fb + linenum * vid_priv->line_length + x * pbytes;
 238        line = start;
 239
 240        for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
 241                unsigned int idx = (u8)ch * VIDEO_FONT_HEIGHT + row;
 242                uchar bits = video_fontdata[idx];
 243
 244                switch (vid_priv->bpix) {
 245                case VIDEO_BPP8:
 246                        if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
 247                                uint8_t *dst = line;
 248
 249                                for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
 250                                        *dst-- = (bits & 0x80) ?
 251                                                vid_priv->colour_fg :
 252                                                vid_priv->colour_bg;
 253                                        bits <<= 1;
 254                                }
 255                                break;
 256                        }
 257                case VIDEO_BPP16:
 258                        if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
 259                                uint16_t *dst = line;
 260
 261                                for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
 262                                        *dst-- = (bits & 0x80) ?
 263                                                vid_priv->colour_fg :
 264                                                vid_priv->colour_bg;
 265                                        bits <<= 1;
 266                                }
 267                                break;
 268                        }
 269                case VIDEO_BPP32:
 270                        if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
 271                                uint32_t *dst = line;
 272
 273                                for (i = 0; i < VIDEO_FONT_WIDTH; i++) {
 274                                        *dst-- = (bits & 0x80) ?
 275                                                vid_priv->colour_fg :
 276                                                vid_priv->colour_bg;
 277                                        bits <<= 1;
 278                                }
 279                                break;
 280                        }
 281                default:
 282                        return -ENOSYS;
 283                }
 284                line -= vid_priv->line_length;
 285        }
 286        /* Add 4 bytes to allow for the first pixel writen */
 287        ret = vidconsole_sync_copy(dev, start + 4, line);
 288        if (ret)
 289                return ret;
 290
 291        return VID_TO_POS(VIDEO_FONT_WIDTH);
 292}
 293
 294static int console_set_row_3(struct udevice *dev, uint row, int clr)
 295{
 296        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 297        int pbytes = VNBYTES(vid_priv->bpix);
 298        void *start, *line;
 299        int i, j, ret;
 300
 301        start = vid_priv->fb + row * VIDEO_FONT_HEIGHT * pbytes;
 302        line = start;
 303        for (j = 0; j < vid_priv->ysize; j++) {
 304                switch (vid_priv->bpix) {
 305                case VIDEO_BPP8:
 306                        if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
 307                                uint8_t *dst = line;
 308
 309                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
 310                                        *dst++ = clr;
 311                                break;
 312                        }
 313                case VIDEO_BPP16:
 314                        if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
 315                                uint16_t *dst = line;
 316
 317                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
 318                                        *dst++ = clr;
 319                                break;
 320                        }
 321                case VIDEO_BPP32:
 322                        if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
 323                                uint32_t *dst = line;
 324
 325                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++)
 326                                        *dst++ = clr;
 327                                break;
 328                        }
 329                default:
 330                        return -ENOSYS;
 331                }
 332                line += vid_priv->line_length;
 333        }
 334        ret = vidconsole_sync_copy(dev, start, line);
 335        if (ret)
 336                return ret;
 337
 338        return 0;
 339}
 340
 341static int console_move_rows_3(struct udevice *dev, uint rowdst, uint rowsrc,
 342                               uint count)
 343{
 344        struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
 345        int pbytes = VNBYTES(vid_priv->bpix);
 346        void *dst;
 347        void *src;
 348        int j, ret;
 349
 350        dst = vid_priv->fb + rowdst * VIDEO_FONT_HEIGHT * pbytes;
 351        src = vid_priv->fb + rowsrc * VIDEO_FONT_HEIGHT * pbytes;
 352
 353        for (j = 0; j < vid_priv->ysize; j++) {
 354                ret = vidconsole_memmove(dev, dst, src,
 355                                         VIDEO_FONT_HEIGHT * pbytes * count);
 356                if (ret)
 357                        return ret;
 358                src += vid_priv->line_length;
 359                dst += vid_priv->line_length;
 360        }
 361
 362        return 0;
 363}
 364
 365static int console_putc_xy_3(struct udevice *dev, uint x_frac, uint y, char ch)
 366{
 367        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
 368        struct udevice *vid = dev->parent;
 369        struct video_priv *vid_priv = dev_get_uclass_priv(vid);
 370        uchar *pfont = video_fontdata + (u8)ch * VIDEO_FONT_HEIGHT;
 371        int pbytes = VNBYTES(vid_priv->bpix);
 372        int i, col, x, ret;
 373        int mask = 0x80;
 374        void *start, *line;
 375
 376        if (x_frac + VID_TO_POS(vc_priv->x_charsize) > vc_priv->xsize_frac)
 377                return -EAGAIN;
 378        x = vid_priv->ysize - VID_TO_PIXEL(x_frac) - 1;
 379        start = vid_priv->fb + x * vid_priv->line_length + y * pbytes;
 380        line = start;
 381        for (col = 0; col < VIDEO_FONT_HEIGHT; col++) {
 382                switch (vid_priv->bpix) {
 383                case VIDEO_BPP8:
 384                        if (IS_ENABLED(CONFIG_VIDEO_BPP8)) {
 385                                uint8_t *dst = line;
 386
 387                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
 388                                        *dst++ = (pfont[i] & mask) ?
 389                                                vid_priv->colour_fg :
 390                                                vid_priv->colour_bg;
 391                                }
 392                                break;
 393                        }
 394                case VIDEO_BPP16:
 395                        if (IS_ENABLED(CONFIG_VIDEO_BPP16)) {
 396                                uint16_t *dst = line;
 397
 398                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
 399                                        *dst++ = (pfont[i] & mask) ?
 400                                                vid_priv->colour_fg :
 401                                                vid_priv->colour_bg;
 402                                }
 403                                break;
 404                        }
 405                case VIDEO_BPP32:
 406                        if (IS_ENABLED(CONFIG_VIDEO_BPP32)) {
 407                                uint32_t *dst = line;
 408
 409                                for (i = 0; i < VIDEO_FONT_HEIGHT; i++) {
 410                                        *dst++ = (pfont[i] & mask) ?
 411                                                vid_priv->colour_fg :
 412                                                vid_priv->colour_bg;
 413                                }
 414                                break;
 415                        }
 416                default:
 417                        return -ENOSYS;
 418                }
 419                line -= vid_priv->line_length;
 420                mask >>= 1;
 421        }
 422        /* Add a line to allow for the first pixels writen */
 423        ret = vidconsole_sync_copy(dev, start + vid_priv->line_length, line);
 424        if (ret)
 425                return ret;
 426
 427        return VID_TO_POS(VIDEO_FONT_WIDTH);
 428}
 429
 430
 431static int console_probe_2(struct udevice *dev)
 432{
 433        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
 434        struct udevice *vid_dev = dev->parent;
 435        struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
 436
 437        vc_priv->x_charsize = VIDEO_FONT_WIDTH;
 438        vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
 439        vc_priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
 440        vc_priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
 441
 442        return 0;
 443}
 444
 445static int console_probe_1_3(struct udevice *dev)
 446{
 447        struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
 448        struct udevice *vid_dev = dev->parent;
 449        struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
 450
 451        vc_priv->x_charsize = VIDEO_FONT_WIDTH;
 452        vc_priv->y_charsize = VIDEO_FONT_HEIGHT;
 453        vc_priv->cols = vid_priv->ysize / VIDEO_FONT_WIDTH;
 454        vc_priv->rows = vid_priv->xsize / VIDEO_FONT_HEIGHT;
 455        vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
 456
 457        return 0;
 458}
 459
 460struct vidconsole_ops console_ops_1 = {
 461        .putc_xy        = console_putc_xy_1,
 462        .move_rows      = console_move_rows_1,
 463        .set_row        = console_set_row_1,
 464};
 465
 466struct vidconsole_ops console_ops_2 = {
 467        .putc_xy        = console_putc_xy_2,
 468        .move_rows      = console_move_rows_2,
 469        .set_row        = console_set_row_2,
 470};
 471
 472struct vidconsole_ops console_ops_3 = {
 473        .putc_xy        = console_putc_xy_3,
 474        .move_rows      = console_move_rows_3,
 475        .set_row        = console_set_row_3,
 476};
 477
 478U_BOOT_DRIVER(vidconsole_1) = {
 479        .name   = "vidconsole1",
 480        .id     = UCLASS_VIDEO_CONSOLE,
 481        .ops    = &console_ops_1,
 482        .probe  = console_probe_1_3,
 483};
 484
 485U_BOOT_DRIVER(vidconsole_2) = {
 486        .name   = "vidconsole2",
 487        .id     = UCLASS_VIDEO_CONSOLE,
 488        .ops    = &console_ops_2,
 489        .probe  = console_probe_2,
 490};
 491
 492U_BOOT_DRIVER(vidconsole_3) = {
 493        .name   = "vidconsole3",
 494        .id     = UCLASS_VIDEO_CONSOLE,
 495        .ops    = &console_ops_3,
 496        .probe  = console_probe_1_3,
 497};
 498