// 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 */ #include #include #include #include #include #include /* Get font data, width and height */ #include "vidconsole_internal.h" struct console_store { int xpos_frac; int ypos; int cli_index; }; static int console_set_row(struct udevice *dev, uint row, int clr) { struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent); struct console_simple_priv *priv = dev_get_priv(dev); struct video_fontdata *fontdata = priv->fontdata; void *line, *dst, *end; int pixels = fontdata->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 * fontdata->height * vid_priv->line_length; dst = line; pbytes = VNBYTES(vid_priv->bpix); for (i = 0; i < pixels; i++) fill_pixel_and_goto_next(&dst, clr, pbytes, pbytes); end = dst; video_damage(dev->parent, 0, fontdata->height * row, vid_priv->xsize, fontdata->height); return 0; } 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); struct console_simple_priv *priv = dev_get_priv(dev); struct video_fontdata *fontdata = priv->fontdata; void *dst; void *src; int size; dst = vid_priv->fb + rowdst * fontdata->height * vid_priv->line_length; src = vid_priv->fb + rowsrc * fontdata->height * vid_priv->line_length; size = fontdata->height * vid_priv->line_length * count; memmove(dst, src, size); video_damage(dev->parent, 0, fontdata->height * rowdst, vid_priv->xsize, fontdata->height * count); return 0; } int console_normal_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) { struct console_simple_priv *priv = dev_get_priv(dev); return console_fixed_putc_xy(dev, x_frac, y, cp, priv->fontdata); } static __maybe_unused int console_get_cursor_info(struct udevice *dev) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct console_simple_priv *priv = dev_get_priv(dev); struct video_fontdata *fontdata = priv->fontdata; struct vidconsole_cursor *curs = &vc_priv->curs; int x, y, index, xspace, xpos; /* for now, this is not used outside expo */ if (!IS_ENABLED(CONFIG_EXPO)) return -ENOSYS; x = VID_TO_PIXEL(vc_priv->xmark_frac); y = vc_priv->ymark; index = vc_priv->cli_index; /* rounded up character position in this line */ xpos = (x + vc_priv->x_charsize - 1) / vc_priv->x_charsize; /* number of characters which can fit on this (first) line */ xspace = vc_priv->cols - xpos; if (!curs->indent && index > xspace) { /* move to the next line */ y += vc_priv->y_charsize; index -= xspace; /* figure out the available space in subsequent lines */ if (!curs->indent) { xspace = vc_priv->cols; x = 0; } /* calculate the line based on that */ y += index / xspace; x += (index % xspace) * fontdata->width; } else { x += index * fontdata->width; } /* place the cursor 1 pixel before the start of the next char */ if (x > 0) x -= 1; /* Store line pointer and height in cursor struct */ curs->x = x; curs->y = y; curs->height = vc_priv->y_charsize; curs->index = vc_priv->cli_index; return 0; } static __maybe_unused int normal_entry_save(struct udevice *dev, struct abuf *buf) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct console_store store; const uint size = sizeof(store); if (xpl_phase() <= PHASE_SPL) return -ENOSYS; if (!abuf_realloc(buf, size)) return log_msg_ret("sav", -ENOMEM); store.xpos_frac = vc_priv->xcur_frac; store.ypos = vc_priv->ycur; store.cli_index = vc_priv->cli_index; memcpy(abuf_data(buf), &store, size); return 0; } static __maybe_unused int normal_entry_restore(struct udevice *dev, struct abuf *buf) { struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev); struct console_store store; if (xpl_phase() <= PHASE_SPL) return -ENOSYS; memcpy(&store, abuf_data(buf), sizeof(store)); vc_priv->xcur_frac = store.xpos_frac; vc_priv->ycur = store.ypos; vc_priv->cli_index = store.cli_index; return 0; } static int console_putc_xy(struct udevice *dev, uint x_frac, uint y, int cp) { return console_normal_putc_xy(dev, x_frac, y, cp); } struct vidconsole_ops console_ops = { .putc_xy = console_putc_xy, .move_rows = console_move_rows, .set_row = console_set_row, .get_font_size = console_simple_get_font_size, .get_font = console_simple_get_font, .select_font = console_simple_select_font, #ifdef CONFIG_CURSOR .get_cursor_info = console_get_cursor_info, .entry_save = normal_entry_save, .entry_restore = normal_entry_restore, #endif }; U_BOOT_DRIVER(vidconsole_normal) = { .name = "vidconsole0", .id = UCLASS_VIDEO_CONSOLE, .ops = &console_ops, .probe = console_probe, .priv_auto = sizeof(struct console_simple_priv), };