1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2a29b0120SSimon Glass /*
3a29b0120SSimon Glass  * Copyright (c) 2016 Google, Inc
4a29b0120SSimon Glass  */
5a29b0120SSimon Glass 
6a29b0120SSimon Glass #include <common.h>
7a29b0120SSimon Glass #include <dm.h>
8a29b0120SSimon Glass #include <video.h>
9a29b0120SSimon Glass #include <video_console.h>
10a29b0120SSimon Glass 
11a29b0120SSimon Glass /* Functions needed by stb_truetype.h */
tt_floor(double val)12a29b0120SSimon Glass static int tt_floor(double val)
13a29b0120SSimon Glass {
14a29b0120SSimon Glass 	if (val < 0)
15a29b0120SSimon Glass 		return (int)(val - 0.999);
16a29b0120SSimon Glass 
17a29b0120SSimon Glass 	return (int)val;
18a29b0120SSimon Glass }
19a29b0120SSimon Glass 
tt_ceil(double val)20a29b0120SSimon Glass static int tt_ceil(double val)
21a29b0120SSimon Glass {
22a29b0120SSimon Glass 	if (val < 0)
23a29b0120SSimon Glass 		return (int)val;
24a29b0120SSimon Glass 
25a29b0120SSimon Glass 	return (int)(val + 0.999);
26a29b0120SSimon Glass }
27a29b0120SSimon Glass 
frac(double val)28a29b0120SSimon Glass static double frac(double val)
29a29b0120SSimon Glass {
30a29b0120SSimon Glass 	return val - tt_floor(val);
31a29b0120SSimon Glass }
32a29b0120SSimon Glass 
tt_fabs(double x)33a29b0120SSimon Glass static double tt_fabs(double x)
34a29b0120SSimon Glass {
35a29b0120SSimon Glass 	return x < 0 ? -x : x;
36a29b0120SSimon Glass }
37a29b0120SSimon Glass 
38a29b0120SSimon Glass  /*
39a29b0120SSimon Glass   * Simple square root algorithm. This is from:
40a29b0120SSimon Glass   * http://stackoverflow.com/questions/1623375/writing-your-own-square-root-function
41a29b0120SSimon Glass   * Written by Chihung Yu
42a29b0120SSimon Glass   * Creative Commons license
43a29b0120SSimon Glass   * http://creativecommons.org/licenses/by-sa/3.0/legalcode
44a29b0120SSimon Glass   * It has been modified to compile correctly, and for U-Boot style.
45a29b0120SSimon Glass   */
tt_sqrt(double value)46a29b0120SSimon Glass static double tt_sqrt(double value)
47a29b0120SSimon Glass {
48a29b0120SSimon Glass 	double lo = 1.0;
49a29b0120SSimon Glass 	double hi = value;
50a29b0120SSimon Glass 
51a29b0120SSimon Glass 	while (hi - lo > 0.00001) {
52a29b0120SSimon Glass 		double mid = lo + (hi - lo) / 2;
53a29b0120SSimon Glass 
54a29b0120SSimon Glass 		if (mid * mid - value > 0.00001)
55a29b0120SSimon Glass 			hi = mid;
56a29b0120SSimon Glass 		else
57a29b0120SSimon Glass 			lo = mid;
58a29b0120SSimon Glass 	}
59a29b0120SSimon Glass 
60a29b0120SSimon Glass 	return lo;
61a29b0120SSimon Glass }
62a29b0120SSimon Glass 
63a29b0120SSimon Glass #define STBTT_ifloor		tt_floor
64a29b0120SSimon Glass #define STBTT_iceil		tt_ceil
65a29b0120SSimon Glass #define STBTT_fabs		tt_fabs
66a29b0120SSimon Glass #define STBTT_sqrt		tt_sqrt
67a29b0120SSimon Glass #define STBTT_malloc(size, u)	((void)(u), malloc(size))
68a29b0120SSimon Glass #define STBTT_free(size, u)	((void)(u), free(size))
69a29b0120SSimon Glass #define STBTT_assert(x)
70a29b0120SSimon Glass #define STBTT_strlen(x)		strlen(x)
71a29b0120SSimon Glass #define STBTT_memcpy		memcpy
72a29b0120SSimon Glass #define STBTT_memset		memset
73a29b0120SSimon Glass 
74a29b0120SSimon Glass #define STB_TRUETYPE_IMPLEMENTATION
75a29b0120SSimon Glass #include "stb_truetype.h"
76a29b0120SSimon Glass 
77a29b0120SSimon Glass /**
78a29b0120SSimon Glass  * struct pos_info - Records a cursor position
79a29b0120SSimon Glass  *
80a29b0120SSimon Glass  * @xpos_frac:	Fractional X position in pixels (multiplied by VID_FRAC_DIV)
81a29b0120SSimon Glass  * @ypos:	Y position (pixels from the top)
82a29b0120SSimon Glass  */
83a29b0120SSimon Glass struct pos_info {
84a29b0120SSimon Glass 	int xpos_frac;
85a29b0120SSimon Glass 	int ypos;
86a29b0120SSimon Glass };
87a29b0120SSimon Glass 
88a29b0120SSimon Glass /*
89a29b0120SSimon Glass  * Allow one for each character on the command line plus one for each newline.
90a29b0120SSimon Glass  * This is just an estimate, but it should not be exceeded.
91a29b0120SSimon Glass  */
92a29b0120SSimon Glass #define POS_HISTORY_SIZE	(CONFIG_SYS_CBSIZE * 11 / 10)
93a29b0120SSimon Glass 
94a29b0120SSimon Glass /**
95a29b0120SSimon Glass  * struct console_tt_priv - Private data for this driver
96a29b0120SSimon Glass  *
97a29b0120SSimon Glass  * @font_size:	Vertical font size in pixels
98a29b0120SSimon Glass  * @font_data:	Pointer to TrueType font file contents
99a29b0120SSimon Glass  * @font:	TrueType font information for the current font
100a29b0120SSimon Glass  * @pos:	List of cursor positions for each character written. This is
101a29b0120SSimon Glass  *		used to handle backspace. We clear the frame buffer between
102a29b0120SSimon Glass  *		the last position and the current position, thus erasing the
103a29b0120SSimon Glass  *		last character. We record enough characters to go back to the
104a29b0120SSimon Glass  *		start of the current command line.
105a29b0120SSimon Glass  * @pos_ptr:	Current position in the position history
106a29b0120SSimon Glass  * @baseline:	Pixel offset of the font's baseline from the cursor position.
107a29b0120SSimon Glass  *		This is the 'ascent' of the font, scaled to pixel coordinates.
108a29b0120SSimon Glass  *		It measures the distance from the baseline to the top of the
109a29b0120SSimon Glass  *		font.
110a29b0120SSimon Glass  * @scale:	Scale of the font. This is calculated from the pixel height
111a29b0120SSimon Glass  *		of the font. It is used by the STB library to generate images
112a29b0120SSimon Glass  *		of the correct size.
113a29b0120SSimon Glass  */
114a29b0120SSimon Glass struct console_tt_priv {
115a29b0120SSimon Glass 	int font_size;
116a29b0120SSimon Glass 	u8 *font_data;
117a29b0120SSimon Glass 	stbtt_fontinfo font;
118a29b0120SSimon Glass 	struct pos_info pos[POS_HISTORY_SIZE];
119a29b0120SSimon Glass 	int pos_ptr;
120a29b0120SSimon Glass 	int baseline;
121a29b0120SSimon Glass 	double scale;
122a29b0120SSimon Glass };
123a29b0120SSimon Glass 
console_truetype_set_row(struct udevice * dev,uint row,int clr)124a29b0120SSimon Glass static int console_truetype_set_row(struct udevice *dev, uint row, int clr)
125a29b0120SSimon Glass {
126a29b0120SSimon Glass 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
127a29b0120SSimon Glass 	struct console_tt_priv *priv = dev_get_priv(dev);
128a29b0120SSimon Glass 	void *line;
129a29b0120SSimon Glass 	int pixels = priv->font_size * vid_priv->line_length;
130a29b0120SSimon Glass 	int i;
131a29b0120SSimon Glass 
132a29b0120SSimon Glass 	line = vid_priv->fb + row * priv->font_size * vid_priv->line_length;
133a29b0120SSimon Glass 	switch (vid_priv->bpix) {
134a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP8
135a29b0120SSimon Glass 	case VIDEO_BPP8: {
136a29b0120SSimon Glass 		uint8_t *dst = line;
137a29b0120SSimon Glass 
138a29b0120SSimon Glass 		for (i = 0; i < pixels; i++)
139a29b0120SSimon Glass 			*dst++ = clr;
140a29b0120SSimon Glass 		break;
141a29b0120SSimon Glass 	}
142a29b0120SSimon Glass #endif
143a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP16
144a29b0120SSimon Glass 	case VIDEO_BPP16: {
145a29b0120SSimon Glass 		uint16_t *dst = line;
146a29b0120SSimon Glass 
147a29b0120SSimon Glass 		for (i = 0; i < pixels; i++)
148a29b0120SSimon Glass 			*dst++ = clr;
149a29b0120SSimon Glass 		break;
150a29b0120SSimon Glass 	}
151a29b0120SSimon Glass #endif
152a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP32
153a29b0120SSimon Glass 	case VIDEO_BPP32: {
154a29b0120SSimon Glass 		uint32_t *dst = line;
155a29b0120SSimon Glass 
156a29b0120SSimon Glass 		for (i = 0; i < pixels; i++)
157a29b0120SSimon Glass 			*dst++ = clr;
158a29b0120SSimon Glass 		break;
159a29b0120SSimon Glass 	}
160a29b0120SSimon Glass #endif
161a29b0120SSimon Glass 	default:
162a29b0120SSimon Glass 		return -ENOSYS;
163a29b0120SSimon Glass 	}
164a29b0120SSimon Glass 
165a29b0120SSimon Glass 	return 0;
166a29b0120SSimon Glass }
167a29b0120SSimon Glass 
console_truetype_move_rows(struct udevice * dev,uint rowdst,uint rowsrc,uint count)168a29b0120SSimon Glass static int console_truetype_move_rows(struct udevice *dev, uint rowdst,
169a29b0120SSimon Glass 				     uint rowsrc, uint count)
170a29b0120SSimon Glass {
171a29b0120SSimon Glass 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
172a29b0120SSimon Glass 	struct console_tt_priv *priv = dev_get_priv(dev);
173a29b0120SSimon Glass 	void *dst;
174a29b0120SSimon Glass 	void *src;
175a29b0120SSimon Glass 	int i, diff;
176a29b0120SSimon Glass 
177a29b0120SSimon Glass 	dst = vid_priv->fb + rowdst * priv->font_size * vid_priv->line_length;
178a29b0120SSimon Glass 	src = vid_priv->fb + rowsrc * priv->font_size * vid_priv->line_length;
179a29b0120SSimon Glass 	memmove(dst, src, priv->font_size * vid_priv->line_length * count);
180a29b0120SSimon Glass 
181a29b0120SSimon Glass 	/* Scroll up our position history */
182a29b0120SSimon Glass 	diff = (rowsrc - rowdst) * priv->font_size;
183a29b0120SSimon Glass 	for (i = 0; i < priv->pos_ptr; i++)
184a29b0120SSimon Glass 		priv->pos[i].ypos -= diff;
185a29b0120SSimon Glass 
186a29b0120SSimon Glass 	return 0;
187a29b0120SSimon Glass }
188a29b0120SSimon Glass 
console_truetype_putc_xy(struct udevice * dev,uint x,uint y,char ch)189a29b0120SSimon Glass static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
190a29b0120SSimon Glass 				    char ch)
191a29b0120SSimon Glass {
192a29b0120SSimon Glass 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
193a29b0120SSimon Glass 	struct udevice *vid = dev->parent;
194a29b0120SSimon Glass 	struct video_priv *vid_priv = dev_get_uclass_priv(vid);
195a29b0120SSimon Glass 	struct console_tt_priv *priv = dev_get_priv(dev);
196a29b0120SSimon Glass 	stbtt_fontinfo *font = &priv->font;
197a29b0120SSimon Glass 	int width, height, xoff, yoff;
198a29b0120SSimon Glass 	double xpos, x_shift;
199a29b0120SSimon Glass 	int lsb;
200a29b0120SSimon Glass 	int width_frac, linenum;
201a29b0120SSimon Glass 	struct pos_info *pos;
202a29b0120SSimon Glass 	u8 *bits, *data;
203a29b0120SSimon Glass 	int advance;
204a29b0120SSimon Glass 	void *line;
205a29b0120SSimon Glass 	int row;
206a29b0120SSimon Glass 
207a29b0120SSimon Glass 	/* First get some basic metrics about this character */
208a29b0120SSimon Glass 	stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb);
209a29b0120SSimon Glass 
210a29b0120SSimon Glass 	/*
211a29b0120SSimon Glass 	 * First out our current X position in fractional pixels. If we wrote
212a29b0120SSimon Glass 	 * a character previously, using kerning to fine-tune the position of
213a29b0120SSimon Glass 	 * this character */
214a29b0120SSimon Glass 	xpos = frac(VID_TO_PIXEL((double)x));
215a29b0120SSimon Glass 	if (vc_priv->last_ch) {
216a29b0120SSimon Glass 		xpos += priv->scale * stbtt_GetCodepointKernAdvance(font,
217a29b0120SSimon Glass 							vc_priv->last_ch, ch);
218a29b0120SSimon Glass 	}
219a29b0120SSimon Glass 
220a29b0120SSimon Glass 	/*
221a29b0120SSimon Glass 	 * Figure out where the cursor will move to after this character, and
222a29b0120SSimon Glass 	 * abort if we are out of space on this line. Also calculate the
223a29b0120SSimon Glass 	 * effective width of this character, which will be our return value:
224a29b0120SSimon Glass 	 * it dictates how much the cursor will move forward on the line.
225a29b0120SSimon Glass 	 */
226a29b0120SSimon Glass 	x_shift = xpos - (double)tt_floor(xpos);
227a29b0120SSimon Glass 	xpos += advance * priv->scale;
228a29b0120SSimon Glass 	width_frac = (int)VID_TO_POS(xpos);
229a29b0120SSimon Glass 	if (x + width_frac >= vc_priv->xsize_frac)
230a29b0120SSimon Glass 		return -EAGAIN;
231a29b0120SSimon Glass 
232a29b0120SSimon Glass 	/* Write the current cursor position into history */
233a29b0120SSimon Glass 	if (priv->pos_ptr < POS_HISTORY_SIZE) {
234a29b0120SSimon Glass 		pos = &priv->pos[priv->pos_ptr];
235a29b0120SSimon Glass 		pos->xpos_frac = vc_priv->xcur_frac;
236a29b0120SSimon Glass 		pos->ypos = vc_priv->ycur;
237a29b0120SSimon Glass 		priv->pos_ptr++;
238a29b0120SSimon Glass 	}
239a29b0120SSimon Glass 
240a29b0120SSimon Glass 	/*
241a29b0120SSimon Glass 	 * Figure out how much past the start of a pixel we are, and pass this
242a29b0120SSimon Glass 	 * information into the render, which will return a 8-bit-per-pixel
243a29b0120SSimon Glass 	 * image of the character. For empty characters, like ' ', data will
244a29b0120SSimon Glass 	 * return NULL;
245a29b0120SSimon Glass 	 */
246a29b0120SSimon Glass 	data = stbtt_GetCodepointBitmapSubpixel(font, priv->scale, priv->scale,
247a29b0120SSimon Glass 						x_shift, 0, ch, &width, &height,
248a29b0120SSimon Glass 						&xoff, &yoff);
249a29b0120SSimon Glass 	if (!data)
250a29b0120SSimon Glass 		return width_frac;
251a29b0120SSimon Glass 
252a29b0120SSimon Glass 	/* Figure out where to write the character in the frame buffer */
253a29b0120SSimon Glass 	bits = data;
254a29b0120SSimon Glass 	line = vid_priv->fb + y * vid_priv->line_length +
255a29b0120SSimon Glass 		VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix);
256a29b0120SSimon Glass 	linenum = priv->baseline + yoff;
257a29b0120SSimon Glass 	if (linenum > 0)
258a29b0120SSimon Glass 		line += linenum * vid_priv->line_length;
259a29b0120SSimon Glass 
260a29b0120SSimon Glass 	/*
261a29b0120SSimon Glass 	 * Write a row at a time, converting the 8bpp image into the colour
262a29b0120SSimon Glass 	 * depth of the display. We only expect white-on-black or the reverse
263a29b0120SSimon Glass 	 * so the code only handles this simple case.
264a29b0120SSimon Glass 	 */
265a29b0120SSimon Glass 	for (row = 0; row < height; row++) {
266a29b0120SSimon Glass 		switch (vid_priv->bpix) {
267a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP16
268a29b0120SSimon Glass 		case VIDEO_BPP16: {
269a29b0120SSimon Glass 			uint16_t *dst = (uint16_t *)line + xoff;
270a29b0120SSimon Glass 			int i;
271a29b0120SSimon Glass 
272a29b0120SSimon Glass 			for (i = 0; i < width; i++) {
273a29b0120SSimon Glass 				int val = *bits;
274a29b0120SSimon Glass 				int out;
275a29b0120SSimon Glass 
276a29b0120SSimon Glass 				if (vid_priv->colour_bg)
277a29b0120SSimon Glass 					val = 255 - val;
278a29b0120SSimon Glass 				out = val >> 3 |
279a29b0120SSimon Glass 					(val >> 2) << 5 |
280a29b0120SSimon Glass 					(val >> 3) << 11;
281a29b0120SSimon Glass 				if (vid_priv->colour_fg)
282a29b0120SSimon Glass 					*dst++ |= out;
283a29b0120SSimon Glass 				else
284a29b0120SSimon Glass 					*dst++ &= out;
285a29b0120SSimon Glass 				bits++;
286a29b0120SSimon Glass 			}
287a29b0120SSimon Glass 			break;
288a29b0120SSimon Glass 		}
289a29b0120SSimon Glass #endif
290a29b0120SSimon Glass 		default:
291f6e75ba7SSimon Glass 			free(data);
292a29b0120SSimon Glass 			return -ENOSYS;
293a29b0120SSimon Glass 		}
294a29b0120SSimon Glass 
295a29b0120SSimon Glass 		line += vid_priv->line_length;
296a29b0120SSimon Glass 	}
297a29b0120SSimon Glass 	free(data);
298a29b0120SSimon Glass 
299a29b0120SSimon Glass 	return width_frac;
300a29b0120SSimon Glass }
301a29b0120SSimon Glass 
302a29b0120SSimon Glass /**
303a29b0120SSimon Glass  * console_truetype_erase() - Erase a character
304a29b0120SSimon Glass  *
305a29b0120SSimon Glass  * This is used for backspace. We erase a square of the display within the
306a29b0120SSimon Glass  * given bounds.
307a29b0120SSimon Glass  *
308a29b0120SSimon Glass  * @dev:	Device to update
309a29b0120SSimon Glass  * @xstart:	X start position in pixels from the left
310a29b0120SSimon Glass  * @ystart:	Y start position in pixels from the top
311a29b0120SSimon Glass  * @xend:	X end position in pixels from the left
312a29b0120SSimon Glass  * @yend:	Y end position  in pixels from the top
313a29b0120SSimon Glass  * @clr:	Value to write
314a29b0120SSimon Glass  * @return 0 if OK, -ENOSYS if the display depth is not supported
315a29b0120SSimon Glass  */
console_truetype_erase(struct udevice * dev,int xstart,int ystart,int xend,int yend,int clr)316a29b0120SSimon Glass static int console_truetype_erase(struct udevice *dev, int xstart, int ystart,
317a29b0120SSimon Glass 				  int xend, int yend, int clr)
318a29b0120SSimon Glass {
319a29b0120SSimon Glass 	struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
320a29b0120SSimon Glass 	void *line;
321a29b0120SSimon Glass 	int pixels = xend - xstart;
322a29b0120SSimon Glass 	int row, i;
323a29b0120SSimon Glass 
324a29b0120SSimon Glass 	line = vid_priv->fb + ystart * vid_priv->line_length;
325a29b0120SSimon Glass 	line += xstart * VNBYTES(vid_priv->bpix);
326a29b0120SSimon Glass 	for (row = ystart; row < yend; row++) {
327a29b0120SSimon Glass 		switch (vid_priv->bpix) {
328a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP8
329a29b0120SSimon Glass 		case VIDEO_BPP8: {
330a29b0120SSimon Glass 			uint8_t *dst = line;
331a29b0120SSimon Glass 
332a29b0120SSimon Glass 			for (i = 0; i < pixels; i++)
333a29b0120SSimon Glass 				*dst++ = clr;
334a29b0120SSimon Glass 			break;
335a29b0120SSimon Glass 		}
336a29b0120SSimon Glass #endif
337a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP16
338a29b0120SSimon Glass 		case VIDEO_BPP16: {
339a29b0120SSimon Glass 			uint16_t *dst = line;
340a29b0120SSimon Glass 
341a29b0120SSimon Glass 			for (i = 0; i < pixels; i++)
342a29b0120SSimon Glass 				*dst++ = clr;
343a29b0120SSimon Glass 			break;
344a29b0120SSimon Glass 		}
345a29b0120SSimon Glass #endif
346a29b0120SSimon Glass #ifdef CONFIG_VIDEO_BPP32
347a29b0120SSimon Glass 		case VIDEO_BPP32: {
348a29b0120SSimon Glass 			uint32_t *dst = line;
349a29b0120SSimon Glass 
350a29b0120SSimon Glass 			for (i = 0; i < pixels; i++)
351a29b0120SSimon Glass 				*dst++ = clr;
352a29b0120SSimon Glass 			break;
353a29b0120SSimon Glass 		}
354a29b0120SSimon Glass #endif
355a29b0120SSimon Glass 		default:
356a29b0120SSimon Glass 			return -ENOSYS;
357a29b0120SSimon Glass 		}
358a29b0120SSimon Glass 		line += vid_priv->line_length;
359a29b0120SSimon Glass 	}
360a29b0120SSimon Glass 
361a29b0120SSimon Glass 	return 0;
362a29b0120SSimon Glass }
363a29b0120SSimon Glass 
364a29b0120SSimon Glass /**
365a29b0120SSimon Glass  * console_truetype_backspace() - Handle a backspace operation
366a29b0120SSimon Glass  *
367a29b0120SSimon Glass  * This clears the previous character so that the console looks as if it had
368a29b0120SSimon Glass  * not been entered.
369a29b0120SSimon Glass  *
370a29b0120SSimon Glass  * @dev:	Device to update
371a29b0120SSimon Glass  * @return 0 if OK, -ENOSYS if not supported
372a29b0120SSimon Glass  */
console_truetype_backspace(struct udevice * dev)373a29b0120SSimon Glass static int console_truetype_backspace(struct udevice *dev)
374a29b0120SSimon Glass {
375a29b0120SSimon Glass 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
376a29b0120SSimon Glass 	struct console_tt_priv *priv = dev_get_priv(dev);
377a29b0120SSimon Glass 	struct udevice *vid_dev = dev->parent;
378a29b0120SSimon Glass 	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
379a29b0120SSimon Glass 	struct pos_info *pos;
380a29b0120SSimon Glass 	int xend;
381a29b0120SSimon Glass 
382a29b0120SSimon Glass 	/*
383a29b0120SSimon Glass 	 * This indicates a very strange error higher in the stack. The caller
384a29b0120SSimon Glass 	 * has sent out n character and n + 1 backspaces.
385a29b0120SSimon Glass 	 */
386a29b0120SSimon Glass 	if (!priv->pos_ptr)
387a29b0120SSimon Glass 		return -ENOSYS;
388a29b0120SSimon Glass 
389a29b0120SSimon Glass 	/* Pop the last cursor position off the stack */
390a29b0120SSimon Glass 	pos = &priv->pos[--priv->pos_ptr];
391a29b0120SSimon Glass 
392a29b0120SSimon Glass 	/*
393a29b0120SSimon Glass 	 * Figure out the end position for clearing. Normlly it is the current
394a29b0120SSimon Glass 	 * cursor position, but if we are clearing a character on the previous
395a29b0120SSimon Glass 	 * line, we clear from the end of the line.
396a29b0120SSimon Glass 	 */
397a29b0120SSimon Glass 	if (pos->ypos == vc_priv->ycur)
398a29b0120SSimon Glass 		xend = VID_TO_PIXEL(vc_priv->xcur_frac);
399a29b0120SSimon Glass 	else
400a29b0120SSimon Glass 		xend = vid_priv->xsize;
401a29b0120SSimon Glass 
402a29b0120SSimon Glass 	console_truetype_erase(dev, VID_TO_PIXEL(pos->xpos_frac), pos->ypos,
403a29b0120SSimon Glass 			       xend, pos->ypos + vc_priv->y_charsize,
404a29b0120SSimon Glass 			       vid_priv->colour_bg);
405a29b0120SSimon Glass 
406a29b0120SSimon Glass 	/* Move the cursor back to where it was when we pushed this record */
407a29b0120SSimon Glass 	vc_priv->xcur_frac = pos->xpos_frac;
408a29b0120SSimon Glass 	vc_priv->ycur = pos->ypos;
409a29b0120SSimon Glass 
410a29b0120SSimon Glass 	return 0;
411a29b0120SSimon Glass }
412a29b0120SSimon Glass 
console_truetype_entry_start(struct udevice * dev)413a29b0120SSimon Glass static int console_truetype_entry_start(struct udevice *dev)
414a29b0120SSimon Glass {
415a29b0120SSimon Glass 	struct console_tt_priv *priv = dev_get_priv(dev);
416a29b0120SSimon Glass 
417a29b0120SSimon Glass 	/* A new input line has start, so clear our history */
418a29b0120SSimon Glass 	priv->pos_ptr = 0;
419a29b0120SSimon Glass 
420a29b0120SSimon Glass 	return 0;
421a29b0120SSimon Glass }
422a29b0120SSimon Glass 
423a29b0120SSimon Glass /*
424a29b0120SSimon Glass  * Provides a list of fonts which can be obtained at run-time in U-Boot. These
425a29b0120SSimon Glass  * are compiled in by the Makefile.
426a29b0120SSimon Glass  *
427a29b0120SSimon Glass  * At present there is no mechanism to select a particular font - the first
428a29b0120SSimon Glass  * one found is the one that is used. But the build system and the code here
429a29b0120SSimon Glass  * supports multiple fonts, which may be useful for certain firmware screens.
430a29b0120SSimon Glass  */
431a29b0120SSimon Glass struct font_info {
432a29b0120SSimon Glass 	char *name;
433a29b0120SSimon Glass 	u8 *begin;
434a29b0120SSimon Glass 	u8 *end;
435a29b0120SSimon Glass };
436a29b0120SSimon Glass 
437a29b0120SSimon Glass #define FONT_DECL(_name) \
438a29b0120SSimon Glass 	extern u8 __ttf_ ## _name ## _begin[]; \
439a29b0120SSimon Glass 	extern u8 __ttf_ ## _name ## _end[];
440a29b0120SSimon Glass 
441a29b0120SSimon Glass #define FONT_ENTRY(_name)		{ \
442a29b0120SSimon Glass 	.name = #_name, \
443a29b0120SSimon Glass 	.begin = __ttf_ ## _name ## _begin, \
444a29b0120SSimon Glass 	.end = __ttf_ ## _name ## _end, \
445a29b0120SSimon Glass 	}
446a29b0120SSimon Glass 
44784b4791aSSimon Glass FONT_DECL(nimbus_sans_l_regular);
448c43c43cdSSimon Glass FONT_DECL(ankacoder_c75_r);
4497ad4e30dSSimon Glass FONT_DECL(rufscript010);
450c0603b98SSimon Glass FONT_DECL(cantoraone_regular);
45184b4791aSSimon Glass 
452a29b0120SSimon Glass static struct font_info font_table[] = {
45384b4791aSSimon Glass #ifdef CONFIG_CONSOLE_TRUETYPE_NIMBUS
45484b4791aSSimon Glass 	FONT_ENTRY(nimbus_sans_l_regular),
45584b4791aSSimon Glass #endif
456c43c43cdSSimon Glass #ifdef CONFIG_CONSOLE_TRUETYPE_ANKACODER
457c43c43cdSSimon Glass 	FONT_ENTRY(ankacoder_c75_r),
458c43c43cdSSimon Glass #endif
4597ad4e30dSSimon Glass #ifdef CONFIG_CONSOLE_TRUETYPE_RUFSCRIPT
4607ad4e30dSSimon Glass 	FONT_ENTRY(rufscript010),
4617ad4e30dSSimon Glass #endif
462c0603b98SSimon Glass #ifdef CONFIG_CONSOLE_TRUETYPE_CANTORAONE
463c0603b98SSimon Glass 	FONT_ENTRY(cantoraone_regular),
464c0603b98SSimon Glass #endif
465a29b0120SSimon Glass 	{} /* sentinel */
466a29b0120SSimon Glass };
467a29b0120SSimon Glass 
468a29b0120SSimon Glass #define FONT_BEGIN(name)	__ttf_ ## name ## _begin
469a29b0120SSimon Glass #define FONT_END(name)		__ttf_ ## name ## _end
470a29b0120SSimon Glass #define FONT_IS_VALID(name)	(abs(FONT_END(name) - FONT_BEGIN) > 4)
471a29b0120SSimon Glass 
472a29b0120SSimon Glass /**
473a29b0120SSimon Glass  * console_truetype_find_font() - Find a suitable font
474a29b0120SSimon Glass  *
475a29b0120SSimon Glass  * This searched for the first available font.
476a29b0120SSimon Glass  *
477a29b0120SSimon Glass  * @return pointer to the font, or NULL if none is found
478a29b0120SSimon Glass  */
console_truetype_find_font(void)479a29b0120SSimon Glass static u8 *console_truetype_find_font(void)
480a29b0120SSimon Glass {
481a29b0120SSimon Glass 	struct font_info *tab;
482a29b0120SSimon Glass 
483a29b0120SSimon Glass 	for (tab = font_table; tab->begin; tab++) {
484a29b0120SSimon Glass 		if (abs(tab->begin - tab->end) > 4) {
485a29b0120SSimon Glass 			debug("%s: Font '%s', at %p, size %lx\n", __func__,
486a29b0120SSimon Glass 			      tab->name, tab->begin,
487a29b0120SSimon Glass 			      (ulong)(tab->end - tab->begin));
488a29b0120SSimon Glass 			return tab->begin;
489a29b0120SSimon Glass 		}
490a29b0120SSimon Glass 	}
491a29b0120SSimon Glass 
492a29b0120SSimon Glass 	return NULL;
493a29b0120SSimon Glass }
494a29b0120SSimon Glass 
console_truetype_probe(struct udevice * dev)495a29b0120SSimon Glass static int console_truetype_probe(struct udevice *dev)
496a29b0120SSimon Glass {
497a29b0120SSimon Glass 	struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
498a29b0120SSimon Glass 	struct console_tt_priv *priv = dev_get_priv(dev);
499a29b0120SSimon Glass 	struct udevice *vid_dev = dev->parent;
500a29b0120SSimon Glass 	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
501a29b0120SSimon Glass 	stbtt_fontinfo *font = &priv->font;
502a29b0120SSimon Glass 	int ascent;
503a29b0120SSimon Glass 
504a29b0120SSimon Glass 	debug("%s: start\n", __func__);
505a29b0120SSimon Glass 	if (vid_priv->font_size)
506a29b0120SSimon Glass 		priv->font_size = vid_priv->font_size;
507a29b0120SSimon Glass 	else
508a29b0120SSimon Glass 		priv->font_size = CONFIG_CONSOLE_TRUETYPE_SIZE;
509a29b0120SSimon Glass 	priv->font_data = console_truetype_find_font();
510a29b0120SSimon Glass 	if (!priv->font_data) {
511a29b0120SSimon Glass 		debug("%s: Could not find any fonts\n", __func__);
512a29b0120SSimon Glass 		return -EBFONT;
513a29b0120SSimon Glass 	}
514a29b0120SSimon Glass 
515a29b0120SSimon Glass 	vc_priv->x_charsize = priv->font_size;
516a29b0120SSimon Glass 	vc_priv->y_charsize = priv->font_size;
517a29b0120SSimon Glass 	vc_priv->xstart_frac = VID_TO_POS(2);
518a29b0120SSimon Glass 	vc_priv->cols = vid_priv->xsize / priv->font_size;
519a29b0120SSimon Glass 	vc_priv->rows = vid_priv->ysize / priv->font_size;
520a29b0120SSimon Glass 	vc_priv->tab_width_frac = VID_TO_POS(priv->font_size) * 8 / 2;
521a29b0120SSimon Glass 
522a29b0120SSimon Glass 	if (!stbtt_InitFont(font, priv->font_data, 0)) {
523a29b0120SSimon Glass 		debug("%s: Font init failed\n", __func__);
524a29b0120SSimon Glass 		return -EPERM;
525a29b0120SSimon Glass 	}
526a29b0120SSimon Glass 
527a29b0120SSimon Glass 	/* Pre-calculate some things we will need regularly */
528a29b0120SSimon Glass 	priv->scale = stbtt_ScaleForPixelHeight(font, priv->font_size);
529a29b0120SSimon Glass 	stbtt_GetFontVMetrics(font, &ascent, 0, 0);
530a29b0120SSimon Glass 	priv->baseline = (int)(ascent * priv->scale);
531a29b0120SSimon Glass 	debug("%s: ready\n", __func__);
532a29b0120SSimon Glass 
533a29b0120SSimon Glass 	return 0;
534a29b0120SSimon Glass }
535a29b0120SSimon Glass 
536a29b0120SSimon Glass struct vidconsole_ops console_truetype_ops = {
537a29b0120SSimon Glass 	.putc_xy	= console_truetype_putc_xy,
538a29b0120SSimon Glass 	.move_rows	= console_truetype_move_rows,
539a29b0120SSimon Glass 	.set_row	= console_truetype_set_row,
540a29b0120SSimon Glass 	.backspace	= console_truetype_backspace,
541a29b0120SSimon Glass 	.entry_start	= console_truetype_entry_start,
542a29b0120SSimon Glass };
543a29b0120SSimon Glass 
544a29b0120SSimon Glass U_BOOT_DRIVER(vidconsole_truetype) = {
545a29b0120SSimon Glass 	.name	= "vidconsole_tt",
546a29b0120SSimon Glass 	.id	= UCLASS_VIDEO_CONSOLE,
547a29b0120SSimon Glass 	.ops	= &console_truetype_ops,
548a29b0120SSimon Glass 	.probe	= console_truetype_probe,
549a29b0120SSimon Glass 	.priv_auto_alloc_size	= sizeof(struct console_tt_priv),
550a29b0120SSimon Glass };
551