From e3f55646ed98e96b23f4af387e95245d4b071140 Mon Sep 17 00:00:00 2001 From: Mikhail Vanyulin <mikhail.vanyulin@rtsoft.de> Date: Mon, 4 Dec 2023 17:44:06 +0100 Subject: [PATCH] logo: add mem logo This is a fix for issue [746-000092] logo: Implement logo driver to show logo from RAM If CONFIG_LOGO_SECO_MEMLOGO is set, logo driver will get logo memory address and size from dtb. And if this points to a correct data, logo, loaded into memory will be displayed. If some part of dtb node is missing or data in the memory is incorrect, a logo, which was selected by the driver before will be used. It is also necessary to reserve memory to which logo is loaded. Exampled dtb nodes: seco-memlogo { compatible = "seco,memlogo"; address = <0x14000000>; size = <74501>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; logo_reserved: logo@14000000 { reusable; reg = <0x14000000 74501>; }; }; Example script, which will generate logo from logo.png: WIDTH=492 HEIGHT=150 pngtopam logo.png > logo.ppm pnmpad -width $WIDTH -height $HEIGHT logo.ppm > logo_pad.ppm pnmcolormap 224 logo_pad.ppm > colormap pnmremap -floyd -plain -mapfile=colormap logo_pad.ppm > logo_plain.ppm seco-pnmtologo -t clut224 -o logo.dat -f bin logo_plain.ppm Example command to load logo into memory from U-Boot: load mmc 1:3 0x14000000 logo.dat Signed-off-by: Mikhail Vanyulin <mikhail.vanyulin@rtsoft.de> (cherry picked from commit e30bc118a5d2b4fd003c71006980c5b2c06429ca) --- drivers/video/logo/Kconfig | 12 ++++++ drivers/video/logo/logo.c | 75 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index c5ef942ad73a7..685c46e628993 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -43,6 +43,18 @@ config LOGO_PARISC_CLUT224 depends on PARISC default y +config LOGO_SECO_MEMLOGO + bool "Memory based dynamic logo" + depends on LOGO + depends on OF + default y + help + Get logo from memory. Memory address and logo size are taken from + a device tree node. Compatible should be "seco,memlogo". + Address is set by "address", size - by "size". + It is also necessary to reserve memory for logo via + "reserved-memory" node in dtb. + config LOGO_SGI_CLUT224 bool "224-color SGI Linux logo" depends on SGI_IP22 || SGI_IP27 || SGI_IP32 diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index 59b0bc8f4f334..40623314604d3 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c @@ -18,6 +18,10 @@ #include <asm/setup.h> #endif +#ifdef CONFIG_LOGO_SECO_MEMLOGO +#include <linux/of.h> +#endif + static bool nologo; module_param(nologo, bool, 0); MODULE_PARM_DESC(nologo, "Disables startup logo"); @@ -44,6 +48,19 @@ late_initcall_sync(fb_logo_late_init); const struct linux_logo * __ref fb_find_logo(int depth) { const struct linux_logo *logo = NULL; +#ifdef CONFIG_LOGO_SECO_MEMLOGO + u32 logophys = 0; + u32 logosize = 0; + + const char *compatible = "seco,memlogo"; + struct device_node *np; + int ret; + + struct linux_logo *validate_logo = NULL; + unsigned int logo_bpc; + unsigned int logo_size_validate; + unsigned int logo_data_size; +#endif if (nologo || logos_freed) return NULL; @@ -112,6 +129,64 @@ const struct linux_logo * __ref fb_find_logo(int depth) /* EDGEHOG OS logo */ logo = &logo_edgehog_clut224; #endif +#ifdef CONFIG_LOGO_SECO_MEMLOGO + np = of_find_compatible_node(NULL, NULL, compatible); + if (!np) + pr_warn("memlogo: Couldn't find node: %s\n", compatible); + else { + ret = of_property_read_u32(np, "address", &logophys); + if (ret) + pr_warn("memlogo: address is not found in device tree\n"); + ret = of_property_read_u32(np, "size", &logosize); + if (ret) + pr_warn("memlogo: size is not found in device tree\n"); + } + of_node_put(np); + + if (logophys && logosize) { + validate_logo = phys_to_virt(logophys); + + if (validate_logo->type < LINUX_LOGO_MONO || + validate_logo->type > LINUX_LOGO_GRAY256) + return logo; + + switch (validate_logo->type) { + case LINUX_LOGO_MONO: + logo_bpc = 1; + break; + case LINUX_LOGO_VGA16: + logo_bpc = 4; + break; + case LINUX_LOGO_CLUT224: + fallthrough; + case LINUX_LOGO_GRAY256: + logo_bpc = 8; + break; + } + + logo_data_size = DIV_ROUND_UP(validate_logo->width * + validate_logo->height * + logo_bpc, 8); + + logo_size_validate = sizeof(struct linux_logo); + logo_size_validate += logo_data_size; + logo_size_validate += validate_logo->clutsize; + if (logosize < logo_size_validate) { + pr_err("memlogo: logo size is too big. Need to reserve more memory for logo in DT\n"); + return logo; + } + + if (logosize < logo_data_size + (uint32_t)validate_logo->data) + return logo; + if (validate_logo->type == LINUX_LOGO_CLUT224 && + logosize < validate_logo->clutsize + (uint32_t)validate_logo->clut) + return logo; + + validate_logo->data += (size_t)validate_logo; + validate_logo->clut += (size_t)validate_logo; + logo = validate_logo; + } +#endif } return logo; -- GitLab