X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=common%2Flcd.c;h=689d30eb25c9ad898237c92bd7401bfea0a7976b;hb=0ce4af99c07acebf4fce9a91f1099d2460629293;hp=edae835fb0be1e6eb1fccdbf373b42dfc588ee31;hpb=345be0b26734c560e8b33531ab21a1272179c5c3;p=karo-tx-uboot.git diff --git a/common/lcd.c b/common/lcd.c index edae835fb0..689d30eb25 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -4,23 +4,7 @@ * (C) Copyright 2001-2002 * Wolfgang Denk, DENX Software Engineering -- wd@denx.de * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ /************************************************************************/ @@ -42,6 +26,10 @@ #endif #include #include +#include +#include +#include +#include #if defined(CONFIG_CPU_PXA25X) || defined(CONFIG_CPU_PXA27X) || \ defined(CONFIG_CPU_MONAHANS) @@ -57,11 +45,14 @@ #include #endif +#if defined(CONFIG_LCD_DT_SIMPLEFB) +#include +#endif + /************************************************************************/ /* ** FONT DATA */ /************************************************************************/ #include /* Get font data, width and height */ -#include /************************************************************************/ /* ** LOGO DATA */ @@ -74,6 +65,10 @@ # endif #endif +#ifdef CONFIG_SANDBOX +#include +#endif + #ifndef CONFIG_LCD_ALIGNMENT #define CONFIG_LCD_ALIGNMENT PAGE_SIZE #endif @@ -105,7 +100,8 @@ #if LCD_BPP == LCD_MONOCHROME # define COLOR_MASK(c) ((c) | (c) << 1 | (c) << 2 | (c) << 3 | \ (c) << 4 | (c) << 5 | (c) << 6 | (c) << 7) -#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) +#elif (LCD_BPP == LCD_COLOR8) || (LCD_BPP == LCD_COLOR16) || \ + (LCD_BPP == LCD_COLOR32) # define COLOR_MASK(c) (c) #else # error Unsupported LCD BPP. @@ -114,14 +110,12 @@ DECLARE_GLOBAL_DATA_PTR; static void lcd_drawchars(ushort x, ushort y, uchar *str, int count); -static inline void lcd_puts_xy(ushort x, ushort y, uchar *s); static inline void lcd_putc_xy(ushort x, ushort y, uchar c); static int lcd_init(void *lcdbase); static void *lcd_logo(void); -static int lcd_getbgcolor(void); static void lcd_setfgcolor(int color); static void lcd_setbgcolor(int color); @@ -155,6 +149,13 @@ void lcd_sync(void) if (lcd_flush_dcache) flush_dcache_range((u32)lcd_base, (u32)(lcd_base + lcd_get_size(&line_length))); +#elif defined(CONFIG_SANDBOX) && defined(CONFIG_VIDEO_SANDBOX_SDL) + static ulong last_sync; + + if (get_timer(last_sync) > 10) { + sandbox_sdl_sync(lcd_base); + last_sync = get_timer(0); + } #endif } @@ -175,10 +176,20 @@ static void console_scrollup(void) 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, COLOR_MASK(lcd_color_bg), 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++ = COLOR_MASK(lcd_color_bg); + } +#endif lcd_sync(); console_row -= rows; } @@ -212,6 +223,11 @@ static inline void console_newline(void) /*----------------------------------------------------------------------*/ +static void lcd_stub_putc(struct stdio_dev *dev, const char c) +{ + lcd_putc(c); +} + void lcd_putc(const char c) { if (!lcd_is_enabled) { @@ -251,6 +267,11 @@ void lcd_putc(const char c) /*----------------------------------------------------------------------*/ +static void lcd_stub_puts(struct stdio_dev *dev, const char *s) +{ + lcd_puts(s); +} + void lcd_puts(const char *s) { if (!lcd_is_enabled) { @@ -296,13 +317,15 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) ushort off = x * (1 << LCD_BPP) % 8; #endif - dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_BPP) / 8); + dest = (uchar *)(lcd_base + 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 @@ -335,6 +358,12 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) lcd_color_fg : lcd_color_bg; bits <<= 1; } +#elif LCD_BPP == LCD_COLOR32 + for (c = 0; c < 8; ++c) { + *d++ = (bits & 0x80) ? + lcd_color_fg : lcd_color_bg; + bits <<= 1; + } #endif } #if LCD_BPP == LCD_MONOCHROME @@ -343,15 +372,6 @@ static void lcd_drawchars(ushort x, ushort y, uchar *str, int count) } } -/*----------------------------------------------------------------------*/ - -static inline void lcd_puts_xy(ushort x, ushort y, uchar *s) -{ - lcd_drawchars(x, y, s, strlen((char *)s)); -} - -/*----------------------------------------------------------------------*/ - static inline void lcd_putc_xy(ushort x, ushort y, uchar c) { lcd_drawchars(x, y, &c, 1); @@ -397,8 +417,13 @@ static void test_pattern(void) /************************************************************************/ /* ** GENERIC Initialization Routines */ /************************************************************************/ - -int lcd_get_size(int *line_length) +/* + * With most lcd drivers the line length is set up + * by calculating it from panel_info parameters. Some + * drivers need to calculate the line length differently, + * so make the function weak to allow overriding it. + */ +__weak int lcd_get_size(int *line_length) { *line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; return *line_length * panel_info.vl_row; @@ -409,7 +434,7 @@ int drv_lcd_init(void) struct stdio_dev lcddev; int rc; - lcd_base = (void *) gd->fb_base; + lcd_base = map_sysmem(gd->fb_base, 0); lcd_init(lcd_base); /* LCD initialization */ @@ -419,8 +444,8 @@ int drv_lcd_init(void) strcpy(lcddev.name, "lcd"); lcddev.ext = 0; /* No extensions */ lcddev.flags = DEV_FLAGS_OUTPUT; /* Output only */ - lcddev.putc = lcd_putc; /* 'putc' function */ - lcddev.puts = lcd_puts; /* 'puts' function */ + lcddev.putc = lcd_stub_putc; /* 'putc' function */ + lcddev.puts = lcd_stub_puts; /* 'puts' function */ rc = stdio_register(&lcddev); @@ -459,9 +484,19 @@ void lcd_clear(void) test_pattern(); #else /* set framebuffer to background color */ +#if (LCD_BPP != LCD_COLOR32) memset((char *)lcd_base, - COLOR_MASK(lcd_getbgcolor()), + COLOR_MASK(lcd_color_bg), lcd_line_length * panel_info.vl_row); +#else + u32 *ppix = lcd_base; + u32 i; + for (i = 0; + i < (lcd_line_length * panel_info.vl_row)/NBYTES(panel_info.vl_bpix); + i++) { + *ppix++ = COLOR_MASK(lcd_color_bg); + } +#endif #endif /* Paint the logo and retrieve LCD base address */ debug("[LCD] Drawing the logo...\n"); @@ -500,13 +535,12 @@ static int lcd_init(void *lcdbase) * by setting up gd->fb_base. Check for this condition and fixup * 'lcd_base' address. */ - if ((unsigned long)lcdbase != gd->fb_base) - lcd_base = (void *)gd->fb_base; + if (map_to_sysmem(lcdbase) != gd->fb_base) + lcd_base = map_sysmem(gd->fb_base, 0); debug("[LCD] Using LCD frambuffer at %p\n", lcd_base); lcd_get_size(&lcd_line_length); - lcd_line_length = (panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8; lcd_is_enabled = 1; lcd_clear(); lcd_enable(); @@ -570,20 +604,6 @@ static void lcd_setbgcolor(int color) lcd_color_bg = color; } -/*----------------------------------------------------------------------*/ - -int lcd_getfgcolor(void) -{ - return lcd_color_fg; -} - -/*----------------------------------------------------------------------*/ - -static int lcd_getbgcolor(void) -{ - return lcd_color_bg; -} - /************************************************************************/ /* ** Chipset depending Bitmap / Logo stuff... */ /************************************************************************/ @@ -784,9 +804,9 @@ static void lcd_display_rle8_bitmap(bmp_image_t *bmp, ushort *cmap, uchar *fb, int x, y; int decode = 1; - width = le32_to_cpu(bmp->header.width); - height = le32_to_cpu(bmp->header.height); - bmap = (uchar *)bmp + le32_to_cpu(bmp->header.data_offset); + width = get_unaligned_le32(&bmp->header.width); + height = get_unaligned_le32(&bmp->header.height); + bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset); x = 0; y = height - 1; @@ -893,7 +913,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) ushort *cmap_base = NULL; ushort i, j; uchar *fb; - bmp_image_t *bmp=(bmp_image_t *)bmp_image; + bmp_image_t *bmp = (bmp_image_t *)map_sysmem(bmp_image, 0); uchar *bmap; ushort padded_width; unsigned long width, height, byte_width; @@ -907,9 +927,10 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) return 1; } - width = le32_to_cpu(bmp->header.width); - height = le32_to_cpu(bmp->header.height); - bmp_bpix = le16_to_cpu(bmp->header.bit_count); + width = get_unaligned_le32(&bmp->header.width); + height = get_unaligned_le32(&bmp->header.height); + bmp_bpix = get_unaligned_le16(&bmp->header.bit_count); + colors = 1 << bmp_bpix; bpix = NBITS(panel_info.vl_bpix); @@ -921,12 +942,15 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) return 1; } - /* We support displaying 8bpp BMPs on 16bpp LCDs */ - if (bpix != bmp_bpix && !(bmp_bpix == 8 && bpix == 16)) { + /* + * We support displaying 8bpp BMPs on 16bpp LCDs + * and displaying 24bpp BMPs on 32bpp LCDs + * */ + if (bpix != bmp_bpix && + !(bmp_bpix == 8 && bpix == 16) && + !(bmp_bpix == 24 && bpix == 32)) { printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", - bpix, - le16_to_cpu(bmp->header.bit_count)); - + bpix, get_unaligned_le16(&bmp->header.bit_count)); return 1; } @@ -963,7 +987,6 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) } } #endif - /* * BMP format for Monochrome assumes that the state of a * pixel is described on a per Bit basis, not per Byte. @@ -994,15 +1017,16 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) if ((y + height) > panel_info.vl_row) height = panel_info.vl_row - y; - bmap = (uchar *) bmp + le32_to_cpu(bmp->header.data_offset); - fb = (uchar *) (lcd_base + + bmap = (uchar *)bmp + get_unaligned_le32(&bmp->header.data_offset); + fb = (uchar *)(lcd_base + (y + height - 1) * lcd_line_length + x * bpix / 8); switch (bmp_bpix) { case 1: /* pass through */ - case 8: + case 8: { #ifdef CONFIG_LCD_BMP_RLE8 - if (le32_to_cpu(bmp->header.compression) == BMP_BI_RLE8) { + u32 compression = get_unaligned_le32(&bmp->header.compression); + if (compression == BMP_BI_RLE8) { if (bpix != 16) { /* TODO implement render code for bpix != 16 */ printf("Error: only support 16 bpix"); @@ -1032,7 +1056,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) fb -= byte_width + lcd_line_length; } break; - + } #if defined(CONFIG_BMP_16BPP) case 16: for (i = 0; i < height; ++i) { @@ -1045,7 +1069,19 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) } break; #endif /* CONFIG_BMP_16BPP */ - +#if defined(CONFIG_BMP_24BMP) + case 24: + for (i = 0; i < height; ++i) { + for (j = 0; j < width; j++) { + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = 0; + } + fb -= lcd_line_length + width * (bpix / 8); + } + break; +#endif /* CONFIG_BMP_24BMP */ #if defined(CONFIG_BMP_32BPP) case 32: for (i = 0; i < height; ++i) { @@ -1068,18 +1104,6 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) } #endif -#ifdef CONFIG_SPLASH_SCREEN_PREPARE -static inline int splash_screen_prepare(void) -{ - return board_splash_screen_prepare(); -} -#else -static inline int splash_screen_prepare(void) -{ - return 0; -} -#endif - static void *lcd_logo(void) { #ifdef CONFIG_SPLASH_SCREEN @@ -1092,26 +1116,11 @@ static void *lcd_logo(void) do_splash = 0; if (splash_screen_prepare()) - return (void *)gd->fb_base; + return (void *)lcd_base; addr = simple_strtoul (s, NULL, 16); -#ifdef CONFIG_SPLASH_SCREEN_ALIGN - s = getenv("splashpos"); - if (s != NULL) { - if (s[0] == 'm') - x = BMP_ALIGN_CENTER; - else - x = simple_strtol(s, NULL, 0); - - s = strchr(s + 1, ','); - if (s != NULL) { - if (s[1] == 'm') - y = BMP_ALIGN_CENTER; - else - y = simple_strtol (s + 1, NULL, 0); - } - } -#endif /* CONFIG_SPLASH_SCREEN_ALIGN */ + + splash_get_pos(&x, &y); if (bmp_display(addr, x, y) == 0) return (void *)lcd_base; @@ -1182,3 +1191,86 @@ int lcd_get_screen_columns(void) { return CONSOLE_COLS; } + +#if defined(CONFIG_LCD_DT_SIMPLEFB) +static int lcd_dt_simplefb_configure_node(void *blob, int off) +{ + u32 stride; + fdt32_t cells[2]; + int ret; + static const char format[] = +#if LCD_BPP == LCD_COLOR16 + "r5g6b5"; +#else + ""; +#endif + + if (!format[0]) + return -1; + + stride = panel_info.vl_col * 2; + + cells[0] = cpu_to_fdt32(gd->fb_base); + cells[1] = cpu_to_fdt32(stride * panel_info.vl_row); + ret = fdt_setprop(blob, off, "reg", cells, sizeof(cells[0]) * 2); + if (ret < 0) + return -1; + + cells[0] = cpu_to_fdt32(panel_info.vl_col); + ret = fdt_setprop(blob, off, "width", cells, sizeof(cells[0])); + if (ret < 0) + return -1; + + cells[0] = cpu_to_fdt32(panel_info.vl_row); + ret = fdt_setprop(blob, off, "height", cells, sizeof(cells[0])); + if (ret < 0) + return -1; + + cells[0] = cpu_to_fdt32(stride); + ret = fdt_setprop(blob, off, "stride", cells, sizeof(cells[0])); + if (ret < 0) + return -1; + + ret = fdt_setprop(blob, off, "format", format, strlen(format) + 1); + if (ret < 0) + return -1; + + ret = fdt_delprop(blob, off, "status"); + if (ret < 0) + return -1; + + return 0; +} + +int lcd_dt_simplefb_add_node(void *blob) +{ + static const char compat[] = "simple-framebuffer"; + static const char disabled[] = "disabled"; + int off, ret; + + off = fdt_add_subnode(blob, 0, "framebuffer"); + if (off < 0) + return -1; + + ret = fdt_setprop(blob, off, "status", disabled, sizeof(disabled)); + if (ret < 0) + return -1; + + ret = fdt_setprop(blob, off, "compatible", compat, sizeof(compat)); + if (ret < 0) + return -1; + + return lcd_dt_simplefb_configure_node(blob, off); +} + +int lcd_dt_simplefb_enable_existing_node(void *blob) +{ + int off; + + off = fdt_node_offset_by_compatible(blob, -1, "simple-framebuffer"); + if (off < 0) + return -1; + + return lcd_dt_simplefb_configure_node(blob, off); +} +#endif