Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/patch/misc/0005-bootsplash.patch
Views: 3959
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c1index 815b007f81ca..c8642142cfea 1006442--- a/drivers/video/fbdev/core/bootsplash.c3+++ b/drivers/video/fbdev/core/bootsplash.c4@@ -53,6 +53,14 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)5console_unlock();6}78+static void splash_callback_animation(struct work_struct *ignored)9+{10+ if (bootsplash_would_render_now()) {11+ /* This will also re-schedule this delayed worker */12+ splash_callback_redraw_vc(ignored);13+ }14+}15+1617static bool is_fb_compatible(const struct fb_info *info)18{19@@ -103,17 +111,44 @@ static bool is_fb_compatible(const struct fb_info *info)20*/21void bootsplash_render_full(struct fb_info *info)22{23+ bool is_update = false;24+25mutex_lock(&splash_state.data_lock);2627- if (!is_fb_compatible(info))28- goto out;29+ /*30+ * If we've painted on this FB recently, we don't have to do31+ * the sanity checks and background drawing again.32+ */33+ if (splash_state.splash_fb == info)34+ is_update = true;35+36+37+ if (!is_update) {38+ /* Check whether we actually support this FB. */39+ splash_state.splash_fb = NULL;40+41+ if (!is_fb_compatible(info))42+ goto out;43+44+ /* Draw the background only once */45+ bootsplash_do_render_background(info, splash_state.file);4647- bootsplash_do_render_background(info, splash_state.file);48+ /* Mark this FB as last seen */49+ splash_state.splash_fb = info;50+ }5152- bootsplash_do_render_pictures(info, splash_state.file);53+ bootsplash_do_render_pictures(info, splash_state.file, is_update);5455bootsplash_do_render_flush(info);5657+ bootsplash_do_step_animations(splash_state.file);58+59+ /* Schedule update for animated splash screens */60+ if (splash_state.file->frame_ms > 0)61+ schedule_delayed_work(&splash_state.dwork_animation,62+ msecs_to_jiffies(63+ splash_state.file->frame_ms));64+65out:66mutex_unlock(&splash_state.data_lock);67}68@@ -169,8 +204,14 @@ void bootsplash_enable(void)6970was_enabled = test_and_set_bit(0, &splash_state.enabled);7172- if (!was_enabled)73+ if (!was_enabled) {74+ /* Force a full redraw when the splash is re-activated */75+ mutex_lock(&splash_state.data_lock);76+ splash_state.splash_fb = NULL;77+ mutex_unlock(&splash_state.data_lock);78+79schedule_work(&splash_state.work_redraw_vc);80+ }81}828384@@ -227,6 +268,14 @@ ATTRIBUTE_GROUPS(splash_dev);85*/86static int splash_resume(struct device *device)87{88+ /*89+ * Force full redraw on resume since we've probably lost the90+ * framebuffer's contents meanwhile91+ */92+ mutex_lock(&splash_state.data_lock);93+ splash_state.splash_fb = NULL;94+ mutex_unlock(&splash_state.data_lock);95+96if (bootsplash_would_render_now())97schedule_work(&splash_state.work_redraw_vc);9899@@ -235,6 +284,7 @@ static int splash_resume(struct device *device)100101static int splash_suspend(struct device *device)102{103+ cancel_delayed_work_sync(&splash_state.dwork_animation);104cancel_work_sync(&splash_state.work_redraw_vc);105106return 0;107@@ -296,6 +346,8 @@ void bootsplash_init(void)108set_bit(0, &splash_state.enabled);109110INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);111+ INIT_DELAYED_WORK(&splash_state.dwork_animation,112+ splash_callback_animation);113114115if (!splash_state.bootfile || !strlen(splash_state.bootfile))116diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h117index 0acb383aa4e3..b3a74835d90f 100644118--- a/drivers/video/fbdev/core/bootsplash_internal.h119+++ b/drivers/video/fbdev/core/bootsplash_internal.h120@@ -37,6 +37,8 @@ struct splash_pic_priv {121122struct splash_blob_priv *blobs;123u16 blobs_loaded;124+125+ u16 anim_nextframe;126};127128129@@ -45,6 +47,12 @@ struct splash_file_priv {130const struct splash_file_header *header;131132struct splash_pic_priv *pics;133+134+ /*135+ * A local copy of the frame delay in the header.136+ * We modify it to keep the code simple.137+ */138+ u16 frame_ms;139};140141142@@ -71,6 +79,7 @@ struct splash_priv {143struct platform_device *splash_device;144145struct work_struct work_redraw_vc;146+ struct delayed_work dwork_animation;147148/* Splash data structures including lock for everything below */149struct mutex data_lock;150@@ -88,8 +97,10 @@ struct splash_priv {151void bootsplash_do_render_background(struct fb_info *info,152const struct splash_file_priv *fp);153void bootsplash_do_render_pictures(struct fb_info *info,154- const struct splash_file_priv *fp);155+ const struct splash_file_priv *fp,156+ bool is_update);157void bootsplash_do_render_flush(struct fb_info *info);158+void bootsplash_do_step_animations(struct splash_file_priv *fp);159160161void bootsplash_free_file(struct splash_file_priv *fp);162diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c163index fd807571ab7d..1f661b2d4cc9 100644164--- a/drivers/video/fbdev/core/bootsplash_load.c165+++ b/drivers/video/fbdev/core/bootsplash_load.c166@@ -71,6 +71,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,167{168const struct firmware *fw;169struct splash_file_priv *fp;170+ bool have_anim = false;171unsigned int i;172const u8 *walker;173174@@ -135,6 +136,13 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,175goto err;176}177178+ if (ph->anim_type > SPLASH_ANIM_LOOP_FORWARD) {179+ pr_warn("Picture %u: Unsupported animation type %u.\n",180+ i, ph->anim_type);181+182+ ph->anim_type = SPLASH_ANIM_NONE;183+ }184+185pp->pic_header = ph;186pp->blobs = vzalloc(ph->num_blobs187* sizeof(struct splash_blob_priv));188@@ -202,6 +210,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,189/* Walk over pictures and ensure all blob slots are filled */190for (i = 0; i < fp->header->num_pics; i++) {191struct splash_pic_priv *pp = &fp->pics[i];192+ const struct splash_pic_header *ph = pp->pic_header;193194if (pp->blobs_loaded != pp->pic_header->num_blobs) {195pr_err("Picture %u doesn't have all blob slots filled.\n",196@@ -209,8 +218,20 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,197198goto err;199}200+201+ if (ph->anim_type202+ && ph->num_blobs > 1203+ && ph->anim_loop < pp->blobs_loaded)204+ have_anim = true;205}206207+ if (!have_anim)208+ /* Disable animation timer if there is nothing to animate */209+ fp->frame_ms = 0;210+ else211+ /* Enforce minimum delay between frames */212+ fp->frame_ms = max((u16)20, fp->header->frame_ms);213+214pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",215fw->size,216fp->header->num_pics,217diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c218index 07e3a4eab811..76033606ca8a 100644219--- a/drivers/video/fbdev/core/bootsplash_render.c220+++ b/drivers/video/fbdev/core/bootsplash_render.c221@@ -148,7 +148,8 @@ void bootsplash_do_render_background(struct fb_info *info,222223224void bootsplash_do_render_pictures(struct fb_info *info,225- const struct splash_file_priv *fp)226+ const struct splash_file_priv *fp,227+ bool is_update)228{229unsigned int i;230231@@ -161,7 +162,11 @@ void bootsplash_do_render_pictures(struct fb_info *info,232if (pp->blobs_loaded < 1)233continue;234235- bp = &pp->blobs[0];236+ /* Skip static pictures when refreshing animations */237+ if (ph->anim_type == SPLASH_ANIM_NONE && is_update)238+ continue;239+240+ bp = &pp->blobs[pp->anim_nextframe];241242if (!bp || bp->blob_header->type != 0)243continue;244@@ -351,3 +356,24 @@ void bootsplash_do_render_flush(struct fb_info *info)245info->fbops->fb_copyarea(info, &area);246}247}248+249+250+void bootsplash_do_step_animations(struct splash_file_priv *fp)251+{252+ unsigned int i;253+254+ /* Step every animation once */255+ for (i = 0; i < fp->header->num_pics; i++) {256+ struct splash_pic_priv *pp = &fp->pics[i];257+258+ if (pp->blobs_loaded < 2259+ || pp->pic_header->anim_loop > pp->blobs_loaded)260+ continue;261+262+ if (pp->pic_header->anim_type == SPLASH_ANIM_LOOP_FORWARD) {263+ pp->anim_nextframe++;264+ if (pp->anim_nextframe >= pp->pic_header->num_blobs)265+ pp->anim_nextframe = pp->pic_header->anim_loop;266+ }267+ }268+}269diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h270index 71cedcc68933..b3af0a3c6487 100644271--- a/include/uapi/linux/bootsplash_file.h272+++ b/include/uapi/linux/bootsplash_file.h273@@ -77,7 +77,17 @@ struct splash_file_header {274uint16_t num_blobs;275uint8_t num_pics;276277- uint8_t padding[103];278+ uint8_t unused_1;279+280+ /*281+ * Milliseconds to wait before painting the next frame in282+ * an animation.283+ * This is actually a minimum, as the system is allowed to284+ * stall for longer between frames.285+ */286+ uint16_t frame_ms;287+288+ uint8_t padding[100];289} __attribute__((__packed__));290291292@@ -116,7 +126,23 @@ struct splash_pic_header {293*/294uint16_t position_offset;295296- uint8_t padding[24];297+ /*298+ * Animation type.299+ * 0 - off300+ * 1 - forward loop301+ */302+ uint8_t anim_type;303+304+ /*305+ * Animation loop point.306+ * Actual meaning depends on animation type:307+ * Type 0 - Unused308+ * 1 - Frame at which to restart the forward loop309+ * (allowing for "intro" frames)310+ */311+ uint8_t anim_loop;312+313+ uint8_t padding[22];314} __attribute__((__packed__));315316317@@ -158,4 +184,9 @@ enum splash_position {318SPLASH_POS_FLAG_CORNER = 0x10,319};320321+enum splash_anim_type {322+ SPLASH_ANIM_NONE = 0,323+ SPLASH_ANIM_LOOP_FORWARD = 1,324+};325+326#endif327328329