mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	vidconsole_ops.get_font is documented to return -ENOENT after the last video_fontdata entry. Signed-off-by: Janne Grunau <j@jannau.net>
		
			
				
	
	
		
			250 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// 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 draw_cursor_vertically(void **line, struct video_priv *vid_priv,
 | 
						|
			   uint height, bool direction)
 | 
						|
{
 | 
						|
	int step, line_step, pbytes, ret;
 | 
						|
	uint value;
 | 
						|
	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;
 | 
						|
	}
 | 
						|
 | 
						|
	value = vid_priv->colour_fg;
 | 
						|
 | 
						|
	for (int row = 0; row < height; row++) {
 | 
						|
		dst = *line;
 | 
						|
		for (int col = 0; col < VIDCONSOLE_CURSOR_WIDTH; col++)
 | 
						|
			fill_pixel_and_goto_next(&dst, value, pbytes, step);
 | 
						|
		*line += line_step;
 | 
						|
	}
 | 
						|
	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 info->name ? 0 : -ENOENT;
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 |