1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

drm/panic: Add support for drawing a monochrome graphical logo

Re-use the existing support for boot-up logos to draw a monochrome
graphical logo in the DRM panic handler.  When no suitable graphical
logo is available, the code falls back to the ASCII art penguin logo.

Note that all graphical boot-up logos are freed during late kernel
initialization, hence a copy must be made for later use.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Reviewed-by: Jocelyn Falempe <jfalempe@redhat.com>
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/3f1a5f56213f3e4584773eb2813e212b2dff6d14.1718305355.git.geert+renesas@glider.be
This commit is contained in:
Geert Uytterhoeven 2024-06-13 21:18:05 +02:00 committed by Jocelyn Falempe
parent a40d031d7b
commit 294bbd1f26
2 changed files with 60 additions and 7 deletions

View file

@ -7,11 +7,15 @@
*/ */
#include <linux/font.h> #include <linux/font.h>
#include <linux/init.h>
#include <linux/iosys-map.h> #include <linux/iosys-map.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/kmsg_dump.h> #include <linux/kmsg_dump.h>
#include <linux/linux_logo.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/math.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/overflow.h>
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/types.h> #include <linux/types.h>
@ -88,6 +92,42 @@ static const struct drm_panic_line logo_ascii[] = {
PANIC_LINE(" \\___)=(___/"), PANIC_LINE(" \\___)=(___/"),
}; };
#ifdef CONFIG_LOGO
static const struct linux_logo *logo_mono;
static int drm_panic_setup_logo(void)
{
const struct linux_logo *logo = fb_find_logo(1);
const unsigned char *logo_data;
struct linux_logo *logo_dup;
if (!logo || logo->type != LINUX_LOGO_MONO)
return 0;
/* The logo is __init, so we must make a copy for later use */
logo_data = kmemdup(logo->data,
size_mul(DIV_ROUND_UP(logo->width, BITS_PER_BYTE), logo->height),
GFP_KERNEL);
if (!logo_data)
return -ENOMEM;
logo_dup = kmemdup(logo, sizeof(*logo), GFP_KERNEL);
if (!logo_dup) {
kfree(logo_data);
return -ENOMEM;
}
logo_dup->data = logo_data;
logo_mono = logo_dup;
return 0;
}
device_initcall(drm_panic_setup_logo);
#else
#define logo_mono ((const struct linux_logo *)NULL)
#endif
/* /*
* Color conversion * Color conversion
*/ */
@ -452,15 +492,22 @@ static void draw_panic_static_user(struct drm_scanout_buffer *sb)
u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format); u32 bg_color = convert_from_xrgb8888(CONFIG_DRM_PANIC_BACKGROUND_COLOR, sb->format->format);
const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL); const struct font_desc *font = get_default_font(sb->width, sb->height, NULL, NULL);
struct drm_rect r_screen, r_logo, r_msg; struct drm_rect r_screen, r_logo, r_msg;
unsigned int logo_width, logo_height;
if (!font) if (!font)
return; return;
r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height); r_screen = DRM_RECT_INIT(0, 0, sb->width, sb->height);
r_logo = DRM_RECT_INIT(0, 0, if (logo_mono) {
get_max_line_len(logo_ascii, logo_ascii_lines) * font->width, logo_width = logo_mono->width;
logo_ascii_lines * font->height); logo_height = logo_mono->height;
} else {
logo_width = get_max_line_len(logo_ascii, logo_ascii_lines) * font->width;
logo_height = logo_ascii_lines * font->height;
}
r_logo = DRM_RECT_INIT(0, 0, logo_width, logo_height);
r_msg = DRM_RECT_INIT(0, 0, r_msg = DRM_RECT_INIT(0, 0,
min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width), min(get_max_line_len(panic_msg, msg_lines) * font->width, sb->width),
min(msg_lines * font->height, sb->height)); min(msg_lines * font->height, sb->height));
@ -471,10 +518,14 @@ static void draw_panic_static_user(struct drm_scanout_buffer *sb)
/* Fill with the background color, and draw text on top */ /* Fill with the background color, and draw text on top */
drm_panic_fill(sb, &r_screen, bg_color); drm_panic_fill(sb, &r_screen, bg_color);
if ((r_msg.x1 >= drm_rect_width(&r_logo) || r_msg.y1 >= drm_rect_height(&r_logo)) && if ((r_msg.x1 >= logo_width || r_msg.y1 >= logo_height) &&
drm_rect_width(&r_logo) <= sb->width && drm_rect_height(&r_logo) <= sb->height) { logo_width <= sb->width && logo_height <= sb->height) {
draw_txt_rectangle(sb, font, logo_ascii, logo_ascii_lines, false, &r_logo, if (logo_mono)
fg_color); drm_panic_blit(sb, &r_logo, logo_mono->data, DIV_ROUND_UP(logo_width, 8),
fg_color);
else
draw_txt_rectangle(sb, font, logo_ascii, logo_ascii_lines, false, &r_logo,
fg_color);
} }
draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color); draw_txt_rectangle(sb, font, panic_msg, msg_lines, true, &r_msg, fg_color);
} }

View file

@ -8,6 +8,8 @@ menuconfig LOGO
depends on FB_CORE || SGI_NEWPORT_CONSOLE depends on FB_CORE || SGI_NEWPORT_CONSOLE
help help
Enable and select frame buffer bootup logos. Enable and select frame buffer bootup logos.
Monochrome logos will also be used by the DRM panic handler, if
enabled.
if LOGO if LOGO