u-boot-brain/drivers/video/vidconsole-uclass.c
Simon Glass f1a1247d89 video: Name consoles by their number
We must use the console name in the 'stdout' variable to select the one
we want. At present the name is formed from the driver name with a suffix
indicating the rotation value.

It seems better to name them sequentially since this can be controlled by
driver order. So adjust the code to use 'vidconsole' for the first,
'vidconsole1' for the second, etc.

Signed-off-by: Simon Glass <sjg@chromium.org>
2016-01-21 20:42:36 -07:00

245 lines
5.6 KiB
C

/*
* Copyright (c) 2015 Google, Inc
* (C) Copyright 2001-2015
* DENX Software Engineering -- wd@denx.de
* Compulab Ltd - http://compulab.co.il/
* Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <dm.h>
#include <video.h>
#include <video_console.h>
#include <video_font.h> /* Get font data, width and height */
/* By default we scroll by a single line */
#ifndef CONFIG_CONSOLE_SCROLL_LINES
#define CONFIG_CONSOLE_SCROLL_LINES 1
#endif
int vidconsole_putc_xy(struct udevice *dev, uint x, uint y, char ch)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
if (!ops->putc_xy)
return -ENOSYS;
return ops->putc_xy(dev, x, y, ch);
}
int vidconsole_move_rows(struct udevice *dev, uint rowdst, uint rowsrc,
uint count)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
if (!ops->move_rows)
return -ENOSYS;
return ops->move_rows(dev, rowdst, rowsrc, count);
}
int vidconsole_set_row(struct udevice *dev, uint row, int clr)
{
struct vidconsole_ops *ops = vidconsole_get_ops(dev);
if (!ops->set_row)
return -ENOSYS;
return ops->set_row(dev, row, clr);
}
/* Move backwards one space */
static void vidconsole_back(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
if (--priv->curr_col < 0) {
priv->curr_col = priv->cols - 1;
if (--priv->curr_row < 0)
priv->curr_row = 0;
}
vidconsole_putc_xy(dev, priv->curr_col * VIDEO_FONT_WIDTH,
priv->curr_row * VIDEO_FONT_HEIGHT, ' ');
}
/* Move to a newline, scrolling the display if necessary */
static void vidconsole_newline(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid_dev = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
const int rows = CONFIG_CONSOLE_SCROLL_LINES;
int i;
priv->curr_col = 0;
/* Check if we need to scroll the terminal */
if (++priv->curr_row >= priv->rows) {
vidconsole_move_rows(dev, 0, rows, priv->rows - rows);
for (i = 0; i < rows; i++)
vidconsole_set_row(dev, priv->rows - i - 1,
vid_priv->colour_bg);
priv->curr_row -= rows;
}
video_sync(dev->parent);
}
int vidconsole_put_char(struct udevice *dev, char ch)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
int ret;
switch (ch) {
case '\r':
priv->curr_col = 0;
break;
case '\n':
vidconsole_newline(dev);
break;
case '\t': /* Tab (8 chars alignment) */
priv->curr_col += 8;
priv->curr_col &= ~7;
if (priv->curr_col >= priv->cols)
vidconsole_newline(dev);
break;
case '\b':
vidconsole_back(dev);
break;
default:
/*
* Failure of this function normally indicates an unsupported
* colour depth. Check this and return an error to help with
* diagnosis.
*/
ret = vidconsole_putc_xy(dev,
priv->curr_col * VIDEO_FONT_WIDTH,
priv->curr_row * VIDEO_FONT_HEIGHT,
ch);
if (ret)
return ret;
if (++priv->curr_col >= priv->cols)
vidconsole_newline(dev);
break;
}
return 0;
}
static void vidconsole_putc(struct stdio_dev *sdev, const char ch)
{
struct udevice *dev = sdev->priv;
vidconsole_put_char(dev, ch);
}
static void vidconsole_puts(struct stdio_dev *sdev, const char *s)
{
struct udevice *dev = sdev->priv;
while (*s)
vidconsole_put_char(dev, *s++);
}
/* Set up the number of rows and colours (rotated drivers override this) */
static int vidconsole_pre_probe(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct udevice *vid = dev->parent;
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
priv->rows = vid_priv->ysize / VIDEO_FONT_HEIGHT;
priv->cols = vid_priv->xsize / VIDEO_FONT_WIDTH;
return 0;
}
/* Register the device with stdio */
static int vidconsole_post_probe(struct udevice *dev)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
struct stdio_dev *sdev = &priv->sdev;
int ret;
if (dev->seq) {
snprintf(sdev->name, sizeof(sdev->name), "vidconsole%d",
dev->seq);
} else {
strcpy(sdev->name, "vidconsole");
}
sdev->flags = DEV_FLAGS_OUTPUT;
sdev->putc = vidconsole_putc;
sdev->puts = vidconsole_puts;
sdev->priv = dev;
ret = stdio_register(sdev);
if (ret)
return ret;
return 0;
}
UCLASS_DRIVER(vidconsole) = {
.id = UCLASS_VIDEO_CONSOLE,
.name = "vidconsole0",
.pre_probe = vidconsole_pre_probe,
.post_probe = vidconsole_post_probe,
.per_device_auto_alloc_size = sizeof(struct vidconsole_priv),
};
void vidconsole_position_cursor(struct udevice *dev, unsigned col, unsigned row)
{
struct vidconsole_priv *priv = dev_get_uclass_priv(dev);
priv->curr_col = min_t(short, col, priv->cols - 1);
priv->curr_row = min_t(short, row, priv->rows - 1);
}
static int do_video_setcursor(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
unsigned int col, row;
struct udevice *dev;
if (argc != 3)
return CMD_RET_USAGE;
uclass_first_device(UCLASS_VIDEO_CONSOLE, &dev);
if (!dev)
return CMD_RET_FAILURE;
col = simple_strtoul(argv[1], NULL, 10);
row = simple_strtoul(argv[2], NULL, 10);
vidconsole_position_cursor(dev, col, row);
return 0;
}
static int do_video_puts(cmd_tbl_t *cmdtp, int flag, int argc,
char *const argv[])
{
struct udevice *dev;
const char *s;
if (argc != 2)
return CMD_RET_USAGE;
uclass_first_device(UCLASS_VIDEO_CONSOLE, &dev);
if (!dev)
return CMD_RET_FAILURE;
for (s = argv[1]; *s; s++)
vidconsole_put_char(dev, *s);
return 0;
}
U_BOOT_CMD(
setcurs, 3, 1, do_video_setcursor,
"set cursor position within screen",
" <col> <row> in character"
);
U_BOOT_CMD(
lcdputs, 2, 1, do_video_puts,
"print string on video framebuffer",
" <string>"
);