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 lcd_console_address 15 #define CONSOLE_ROW_SECOND (lcd_console_address + CONSOLE_ROW_SIZE) 16 #define CONSOLE_ROW_LAST (lcd_console_address + CONSOLE_SIZE \ 17 - CONSOLE_ROW_SIZE) 18 #define CONSOLE_SIZE (CONSOLE_ROW_SIZE * console_rows) 19 #define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE) 20 21 static short console_curr_col; 22 static short console_curr_row; 23 static short console_cols; 24 static short console_rows; 25 static void *lcd_console_address; 26 27 void lcd_init_console(void *address, int rows, int cols) 28 { 29 console_curr_col = 0; 30 console_curr_row = 0; 31 console_cols = cols; 32 console_rows = rows; 33 lcd_console_address = address; 34 } 35 36 void lcd_set_col(short col) 37 { 38 console_curr_col = col; 39 } 40 41 void lcd_set_row(short row) 42 { 43 console_curr_row = row; 44 } 45 46 void lcd_position_cursor(unsigned col, unsigned row) 47 { 48 console_curr_col = min_t(short, col, console_cols - 1); 49 console_curr_row = min_t(short, row, console_rows - 1); 50 } 51 52 int lcd_get_screen_rows(void) 53 { 54 return console_rows; 55 } 56 57 int lcd_get_screen_columns(void) 58 { 59 return console_cols; 60 } 61 62 static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) 63 { 64 uchar *dest; 65 ushort row; 66 int fg_color, bg_color; 67 68 dest = (uchar *)(lcd_console_address + 69 y * lcd_line_length + x * NBITS(LCD_BPP) / 8); 70 71 for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) { 72 uchar *s = str; 73 int i; 74 #if LCD_BPP == LCD_COLOR16 75 ushort *d = (ushort *)dest; 76 #elif LCD_BPP == LCD_COLOR32 77 u32 *d = (u32 *)dest; 78 #else 79 uchar *d = dest; 80 #endif 81 82 fg_color = lcd_getfgcolor(); 83 bg_color = lcd_getbgcolor(); 84 for (i = 0; i < count; ++i) { 85 uchar c, bits; 86 87 c = *s++; 88 bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; 89 90 for (c = 0; c < 8; ++c) { 91 *d++ = (bits & 0x80) ? fg_color : bg_color; 92 bits <<= 1; 93 } 94 } 95 } 96 } 97 98 static inline void lcd_putc_xy(ushort x, ushort y, uchar c) 99 { 100 lcd_drawchars(x, y, &c, 1); 101 } 102 103 static void console_scrollup(void) 104 { 105 const int rows = CONFIG_CONSOLE_SCROLL_LINES; 106 int bg_color = lcd_getbgcolor(); 107 108 /* Copy up rows ignoring those that will be overwritten */ 109 memcpy(CONSOLE_ROW_FIRST, 110 lcd_console_address + CONSOLE_ROW_SIZE * rows, 111 CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows); 112 113 /* Clear the last rows */ 114 #if (LCD_BPP != LCD_COLOR32) 115 memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows, 116 bg_color, CONSOLE_ROW_SIZE * rows); 117 #else 118 u32 *ppix = lcd_console_address + 119 CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows; 120 u32 i; 121 for (i = 0; 122 i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix); 123 i++) { 124 *ppix++ = bg_color; 125 } 126 #endif 127 lcd_sync(); 128 console_curr_row -= rows; 129 } 130 131 static inline void console_back(void) 132 { 133 if (--console_curr_col < 0) { 134 console_curr_col = console_cols - 1; 135 if (--console_curr_row < 0) 136 console_curr_row = 0; 137 } 138 139 lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH, 140 console_curr_row * VIDEO_FONT_HEIGHT, ' '); 141 } 142 143 static inline void console_newline(void) 144 { 145 console_curr_col = 0; 146 147 /* Check if we need to scroll the terminal */ 148 if (++console_curr_row >= console_rows) 149 console_scrollup(); 150 else 151 lcd_sync(); 152 } 153 154 void lcd_putc(const char c) 155 { 156 if (!lcd_is_enabled) { 157 serial_putc(c); 158 159 return; 160 } 161 162 switch (c) { 163 case '\r': 164 console_curr_col = 0; 165 166 return; 167 case '\n': 168 console_newline(); 169 170 return; 171 case '\t': /* Tab (8 chars alignment) */ 172 console_curr_col += 8; 173 console_curr_col &= ~7; 174 175 if (console_curr_col >= console_cols) 176 console_newline(); 177 178 return; 179 case '\b': 180 console_back(); 181 182 return; 183 default: 184 lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH, 185 console_curr_row * VIDEO_FONT_HEIGHT, c); 186 if (++console_curr_col >= console_cols) 187 console_newline(); 188 } 189 } 190 191 void lcd_puts(const char *s) 192 { 193 if (!lcd_is_enabled) { 194 serial_puts(s); 195 196 return; 197 } 198 199 while (*s) 200 lcd_putc(*s++); 201 202 lcd_sync(); 203 } 204 205 void lcd_printf(const char *fmt, ...) 206 { 207 va_list args; 208 char buf[CONFIG_SYS_PBSIZE]; 209 210 va_start(args, fmt); 211 vsprintf(buf, fmt, args); 212 va_end(args); 213 214 lcd_puts(buf); 215 } 216