blob: 74c388a0cadccb06a4e9ba935310b78d2206ec3a [file] [log] [blame]
/*
* (C) Copyright 2001-2014
* DENX Software Engineering -- wd@denx.de
* Compulab Ltd - http://compulab.co.il/
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <lcd.h>
#include <video_font.h> /* Get font data, width and height */
#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * lcd_line_length)
#define CONSOLE_ROW_FIRST lcd_console_address
#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * console_rows)
static short console_curr_col;
static short console_curr_row;
static short console_cols;
static short console_rows;
static void *lcd_console_address;
void lcd_init_console(void *address, int rows, int cols)
{
console_curr_col = 0;
console_curr_row = 0;
console_cols = cols;
console_rows = rows;
lcd_console_address = address;
}
void lcd_set_col(short col)
{
console_curr_col = col;
}
void lcd_set_row(short row)
{
console_curr_row = row;
}
void lcd_position_cursor(unsigned col, unsigned row)
{
console_curr_col = min_t(short, col, console_cols - 1);
console_curr_row = min_t(short, row, console_rows - 1);
}
int lcd_get_screen_rows(void)
{
return console_rows;
}
int lcd_get_screen_columns(void)
{
return console_cols;
}
static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
{
uchar *dest;
ushort row;
int fg_color, bg_color;
dest = (uchar *)(lcd_console_address +
y * lcd_line_length + x * NBITS(LCD_BPP) / 8);
for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
uchar *s = str;
int i;
#if LCD_BPP == LCD_COLOR16
ushort *d = (ushort *)dest;
#elif LCD_BPP == LCD_COLOR32
u32 *d = (u32 *)dest;
#else
uchar *d = dest;
#endif
fg_color = lcd_getfgcolor();
bg_color = lcd_getbgcolor();
for (i = 0; i < count; ++i) {
uchar c, bits;
c = *s++;
bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
for (c = 0; c < 8; ++c) {
*d++ = (bits & 0x80) ? fg_color : bg_color;
bits <<= 1;
}
}
}
}
static inline void lcd_putc_xy(ushort x, ushort y, uchar c)
{
lcd_drawchars(x, y, &c, 1);
}
static void console_scrollup(void)
{
const int rows = CONFIG_CONSOLE_SCROLL_LINES;
int bg_color = lcd_getbgcolor();
/* Copy up rows ignoring those that will be overwritten */
memcpy(CONSOLE_ROW_FIRST,
lcd_console_address + CONSOLE_ROW_SIZE * rows,
CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
/* Clear the last rows */
#if (LCD_BPP != LCD_COLOR32)
memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
bg_color, CONSOLE_ROW_SIZE * rows);
#else
u32 *ppix = lcd_console_address +
CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows;
u32 i;
for (i = 0;
i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix);
i++) {
*ppix++ = bg_color;
}
#endif
lcd_sync();
console_curr_row -= rows;
}
static inline void console_back(void)
{
if (--console_curr_col < 0) {
console_curr_col = console_cols - 1;
if (--console_curr_row < 0)
console_curr_row = 0;
}
lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH,
console_curr_row * VIDEO_FONT_HEIGHT, ' ');
}
static inline void console_newline(void)
{
console_curr_col = 0;
/* Check if we need to scroll the terminal */
if (++console_curr_row >= console_rows)
console_scrollup();
else
lcd_sync();
}
void lcd_putc(const char c)
{
if (!lcd_is_enabled) {
serial_putc(c);
return;
}
switch (c) {
case '\r':
console_curr_col = 0;
return;
case '\n':
console_newline();
return;
case '\t': /* Tab (8 chars alignment) */
console_curr_col += 8;
console_curr_col &= ~7;
if (console_curr_col >= console_cols)
console_newline();
return;
case '\b':
console_back();
return;
default:
lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH,
console_curr_row * VIDEO_FONT_HEIGHT, c);
if (++console_curr_col >= console_cols)
console_newline();
}
}
void lcd_puts(const char *s)
{
if (!lcd_is_enabled) {
serial_puts(s);
return;
}
while (*s)
lcd_putc(*s++);
lcd_sync();
}
void lcd_printf(const char *fmt, ...)
{
va_list args;
char buf[CONFIG_SYS_PBSIZE];
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
lcd_puts(buf);
}