1 /* 2 * (C) Copyright 2001-2014 3 * DENX Software Engineering -- wd@denx.de 4 * Compulab Ltd - http://compulab.co.il/ 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <common.h> 10 #include <lcd.h> 11 #include <video_font.h> /* Get font data, width and height */ 12 13 #define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * lcd_line_length) 14 #define CONSOLE_ROW_FIRST cons.lcd_address 15 #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * cons.rows) 16 17 struct console_t { 18 short curr_col, curr_row; 19 short cols, rows; 20 void *lcd_address; 21 }; 22 static struct console_t cons; 23 24 void lcd_init_console(void *address, int rows, int cols) 25 { 26 memset(&cons, 0, sizeof(cons)); 27 cons.cols = cols; 28 cons.rows = rows; 29 cons.lcd_address = address; 30 31 } 32 33 void lcd_set_col(short col) 34 { 35 cons.curr_col = col; 36 } 37 38 void lcd_set_row(short row) 39 { 40 cons.curr_row = row; 41 } 42 43 void lcd_position_cursor(unsigned col, unsigned row) 44 { 45 cons.curr_col = min_t(short, col, cons.cols - 1); 46 cons.curr_row = min_t(short, row, cons.rows - 1); 47 } 48 49 int lcd_get_screen_rows(void) 50 { 51 return cons.rows; 52 } 53 54 int lcd_get_screen_columns(void) 55 { 56 return cons.cols; 57 } 58 59 static void lcd_putc_xy(ushort x, ushort y, char c) 60 { 61 uchar *dest; 62 ushort row; 63 int fg_color = lcd_getfgcolor(); 64 int bg_color = lcd_getbgcolor(); 65 int i; 66 67 dest = (uchar *)(cons.lcd_address + 68 y * lcd_line_length + x * NBITS(LCD_BPP) / 8); 69 70 for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) { 71 #if LCD_BPP == LCD_COLOR16 72 ushort *d = (ushort *)dest; 73 #elif LCD_BPP == LCD_COLOR32 74 u32 *d = (u32 *)dest; 75 #else 76 uchar *d = dest; 77 #endif 78 uchar bits; 79 bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; 80 81 for (i = 0; i < 8; ++i) { 82 *d++ = (bits & 0x80) ? fg_color : bg_color; 83 bits <<= 1; 84 } 85 } 86 } 87 88 static void console_scrollup(void) 89 { 90 const int rows = CONFIG_CONSOLE_SCROLL_LINES; 91 int bg_color = lcd_getbgcolor(); 92 93 /* Copy up rows ignoring those that will be overwritten */ 94 memcpy(CONSOLE_ROW_FIRST, 95 cons.lcd_address + CONSOLE_ROW_SIZE * rows, 96 CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows); 97 98 /* Clear the last rows */ 99 #if (LCD_BPP != LCD_COLOR32) 100 memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows, 101 bg_color, CONSOLE_ROW_SIZE * rows); 102 #else 103 u32 *ppix = cons.lcd_address + 104 CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows; 105 u32 i; 106 for (i = 0; 107 i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix); 108 i++) { 109 *ppix++ = bg_color; 110 } 111 #endif 112 lcd_sync(); 113 cons.curr_row -= rows; 114 } 115 116 static inline void console_back(void) 117 { 118 if (--cons.curr_col < 0) { 119 cons.curr_col = cons.cols - 1; 120 if (--cons.curr_row < 0) 121 cons.curr_row = 0; 122 } 123 124 lcd_putc_xy(cons.curr_col * VIDEO_FONT_WIDTH, 125 cons.curr_row * VIDEO_FONT_HEIGHT, ' '); 126 } 127 128 static inline void console_newline(void) 129 { 130 cons.curr_col = 0; 131 132 /* Check if we need to scroll the terminal */ 133 if (++cons.curr_row >= cons.rows) 134 console_scrollup(); 135 else 136 lcd_sync(); 137 } 138 139 void lcd_putc(const char c) 140 { 141 if (!lcd_is_enabled) { 142 serial_putc(c); 143 144 return; 145 } 146 147 switch (c) { 148 case '\r': 149 cons.curr_col = 0; 150 return; 151 case '\n': 152 console_newline(); 153 154 return; 155 case '\t': /* Tab (8 chars alignment) */ 156 cons.curr_col += 8; 157 cons.curr_col &= ~7; 158 159 if (cons.curr_col >= cons.cols) 160 console_newline(); 161 162 return; 163 case '\b': 164 console_back(); 165 166 return; 167 default: 168 lcd_putc_xy(cons.curr_col * VIDEO_FONT_WIDTH, 169 cons.curr_row * VIDEO_FONT_HEIGHT, c); 170 if (++cons.curr_col >= cons.cols) 171 console_newline(); 172 } 173 } 174 175 void lcd_puts(const char *s) 176 { 177 if (!lcd_is_enabled) { 178 serial_puts(s); 179 180 return; 181 } 182 183 while (*s) 184 lcd_putc(*s++); 185 186 lcd_sync(); 187 } 188 189 void lcd_printf(const char *fmt, ...) 190 { 191 va_list args; 192 char buf[CONFIG_SYS_PBSIZE]; 193 194 va_start(args, fmt); 195 vsprintf(buf, fmt, args); 196 va_end(args); 197 198 lcd_puts(buf); 199 } 200 201 static int do_lcd_setcursor(cmd_tbl_t *cmdtp, int flag, int argc, 202 char *const argv[]) 203 { 204 unsigned int col, row; 205 206 if (argc != 3) 207 return CMD_RET_USAGE; 208 209 col = simple_strtoul(argv[1], NULL, 10); 210 row = simple_strtoul(argv[2], NULL, 10); 211 lcd_position_cursor(col, row); 212 213 return 0; 214 } 215 216 static int do_lcd_puts(cmd_tbl_t *cmdtp, int flag, int argc, 217 char *const argv[]) 218 { 219 if (argc != 2) 220 return CMD_RET_USAGE; 221 222 lcd_puts(argv[1]); 223 224 return 0; 225 } 226 227 U_BOOT_CMD( 228 setcurs, 3, 1, do_lcd_setcursor, 229 "set cursor position within screen", 230 " <col> <row> in character" 231 ); 232 233 U_BOOT_CMD( 234 lcdputs, 2, 1, do_lcd_puts, 235 "print string on lcd-framebuffer", 236 " <string>" 237 ); 238 239