| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- // 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 <video_font.h>
- #include "vidconsole_internal.h"
- /**
- * console_set_font() - prepare vidconsole for chosen font.
- *
- * @dev vidconsole device
- * @fontdata pointer to font data struct
- */
- static int console_set_font(struct udevice *dev, struct video_fontdata *fontdata)
- {
- struct console_simple_priv *priv = dev_get_priv(dev);
- struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
- struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
- debug("console_simple: setting %s font\n", fontdata->name);
- debug("width: %d\n", fontdata->width);
- debug("byte width: %d\n", fontdata->byte_width);
- debug("height: %d\n", fontdata->height);
- priv->fontdata = fontdata;
- vc_priv->x_charsize = fontdata->width;
- vc_priv->y_charsize = fontdata->height;
- if (vid_priv->rot % 2) {
- vc_priv->cols = vid_priv->ysize / fontdata->width;
- vc_priv->rows = vid_priv->xsize / fontdata->height;
- vc_priv->xsize_frac = VID_TO_POS(vid_priv->ysize);
- } else {
- vc_priv->cols = vid_priv->xsize / fontdata->width;
- vc_priv->rows = vid_priv->ysize / fontdata->height;
- }
- return 0;
- }
- int check_bpix_support(int bpix)
- {
- if (bpix == VIDEO_BPP8 && CONFIG_IS_ENABLED(VIDEO_BPP8))
- return 0;
- else if (bpix == VIDEO_BPP16 && CONFIG_IS_ENABLED(VIDEO_BPP16))
- return 0;
- else if (bpix == VIDEO_BPP32 && CONFIG_IS_ENABLED(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,
- struct video_fontdata *fontdata, bool direction)
- {
- int step, line_step, pbytes, bitcount, width_remainder, 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;
- }
- width_remainder = fontdata->width % 8;
- for (int row = 0; row < fontdata->height; row++) {
- uchar bits;
- bitcount = 8;
- dst = *line;
- for (int col = 0; col < fontdata->byte_width; col++) {
- if (width_remainder) {
- bool is_last_col = (fontdata->byte_width - col == 1);
- if (is_last_col)
- bitcount = width_remainder;
- }
- bits = pfont[col];
- for (int bit = 0; bit < bitcount; bit++) {
- 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;
- pfont += fontdata->byte_width;
- }
- return ret;
- }
- int fill_char_horizontally(uchar *pfont, void **line, struct video_priv *vid_priv,
- struct video_fontdata *fontdata, bool direction)
- {
- int step, line_step, pbytes, bitcount = 8, width_remainder, ret;
- void *dst;
- u8 mask;
- 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;
- }
- width_remainder = fontdata->width % 8;
- for (int col = 0; col < fontdata->byte_width; col++) {
- mask = 0x80;
- if (width_remainder) {
- bool is_last_col = (fontdata->byte_width - col == 1);
- if (is_last_col)
- bitcount = width_remainder;
- }
- for (int bit = 0; bit < bitcount; bit++) {
- dst = *line;
- for (int row = 0; row < fontdata->height; row++) {
- u32 value = (pfont[row * fontdata->byte_width + col]
- & 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)
- {
- return console_set_font(dev, fonts);
- }
- const char *console_simple_get_font_size(struct udevice *dev, uint *sizep)
- {
- struct console_simple_priv *priv = dev_get_priv(dev);
- *sizep = priv->fontdata->width;
- return priv->fontdata->name;
- }
- int console_simple_get_font(struct udevice *dev, int seq, struct vidfont_info *info)
- {
- info->name = fonts[seq].name;
- return 0;
- }
- int console_simple_select_font(struct udevice *dev, const char *name, uint size)
- {
- struct video_fontdata *font;
- if (!name) {
- if (fonts->name)
- console_set_font(dev, fonts);
- return 0;
- }
- for (font = fonts; font->name; font++) {
- if (!strcmp(name, font->name)) {
- console_set_font(dev, font);
- return 0;
- }
- };
- printf("no such font: %s, make sure it's name has <width>x<height> format\n", name);
- return -ENOENT;
- }
|