CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: orangepi-xunlong/orangepi-build
Path: blob/next/external/patch/misc/0005-bootsplash.patch
Views: 3959
1
diff --git a/drivers/video/fbdev/core/bootsplash.c b/drivers/video/fbdev/core/bootsplash.c
2
index 815b007f81ca..c8642142cfea 100644
3
--- a/drivers/video/fbdev/core/bootsplash.c
4
+++ b/drivers/video/fbdev/core/bootsplash.c
5
@@ -53,6 +53,14 @@ static void splash_callback_redraw_vc(struct work_struct *ignored)
6
console_unlock();
7
}
8
9
+static void splash_callback_animation(struct work_struct *ignored)
10
+{
11
+ if (bootsplash_would_render_now()) {
12
+ /* This will also re-schedule this delayed worker */
13
+ splash_callback_redraw_vc(ignored);
14
+ }
15
+}
16
+
17
18
static bool is_fb_compatible(const struct fb_info *info)
19
{
20
@@ -103,17 +111,44 @@ static bool is_fb_compatible(const struct fb_info *info)
21
*/
22
void bootsplash_render_full(struct fb_info *info)
23
{
24
+ bool is_update = false;
25
+
26
mutex_lock(&splash_state.data_lock);
27
28
- if (!is_fb_compatible(info))
29
- goto out;
30
+ /*
31
+ * If we've painted on this FB recently, we don't have to do
32
+ * the sanity checks and background drawing again.
33
+ */
34
+ if (splash_state.splash_fb == info)
35
+ is_update = true;
36
+
37
+
38
+ if (!is_update) {
39
+ /* Check whether we actually support this FB. */
40
+ splash_state.splash_fb = NULL;
41
+
42
+ if (!is_fb_compatible(info))
43
+ goto out;
44
+
45
+ /* Draw the background only once */
46
+ bootsplash_do_render_background(info, splash_state.file);
47
48
- bootsplash_do_render_background(info, splash_state.file);
49
+ /* Mark this FB as last seen */
50
+ splash_state.splash_fb = info;
51
+ }
52
53
- bootsplash_do_render_pictures(info, splash_state.file);
54
+ bootsplash_do_render_pictures(info, splash_state.file, is_update);
55
56
bootsplash_do_render_flush(info);
57
58
+ bootsplash_do_step_animations(splash_state.file);
59
+
60
+ /* Schedule update for animated splash screens */
61
+ if (splash_state.file->frame_ms > 0)
62
+ schedule_delayed_work(&splash_state.dwork_animation,
63
+ msecs_to_jiffies(
64
+ splash_state.file->frame_ms));
65
+
66
out:
67
mutex_unlock(&splash_state.data_lock);
68
}
69
@@ -169,8 +204,14 @@ void bootsplash_enable(void)
70
71
was_enabled = test_and_set_bit(0, &splash_state.enabled);
72
73
- if (!was_enabled)
74
+ if (!was_enabled) {
75
+ /* Force a full redraw when the splash is re-activated */
76
+ mutex_lock(&splash_state.data_lock);
77
+ splash_state.splash_fb = NULL;
78
+ mutex_unlock(&splash_state.data_lock);
79
+
80
schedule_work(&splash_state.work_redraw_vc);
81
+ }
82
}
83
84
85
@@ -227,6 +268,14 @@ ATTRIBUTE_GROUPS(splash_dev);
86
*/
87
static int splash_resume(struct device *device)
88
{
89
+ /*
90
+ * Force full redraw on resume since we've probably lost the
91
+ * framebuffer's contents meanwhile
92
+ */
93
+ mutex_lock(&splash_state.data_lock);
94
+ splash_state.splash_fb = NULL;
95
+ mutex_unlock(&splash_state.data_lock);
96
+
97
if (bootsplash_would_render_now())
98
schedule_work(&splash_state.work_redraw_vc);
99
100
@@ -235,6 +284,7 @@ static int splash_resume(struct device *device)
101
102
static int splash_suspend(struct device *device)
103
{
104
+ cancel_delayed_work_sync(&splash_state.dwork_animation);
105
cancel_work_sync(&splash_state.work_redraw_vc);
106
107
return 0;
108
@@ -296,6 +346,8 @@ void bootsplash_init(void)
109
set_bit(0, &splash_state.enabled);
110
111
INIT_WORK(&splash_state.work_redraw_vc, splash_callback_redraw_vc);
112
+ INIT_DELAYED_WORK(&splash_state.dwork_animation,
113
+ splash_callback_animation);
114
115
116
if (!splash_state.bootfile || !strlen(splash_state.bootfile))
117
diff --git a/drivers/video/fbdev/core/bootsplash_internal.h b/drivers/video/fbdev/core/bootsplash_internal.h
118
index 0acb383aa4e3..b3a74835d90f 100644
119
--- a/drivers/video/fbdev/core/bootsplash_internal.h
120
+++ b/drivers/video/fbdev/core/bootsplash_internal.h
121
@@ -37,6 +37,8 @@ struct splash_pic_priv {
122
123
struct splash_blob_priv *blobs;
124
u16 blobs_loaded;
125
+
126
+ u16 anim_nextframe;
127
};
128
129
130
@@ -45,6 +47,12 @@ struct splash_file_priv {
131
const struct splash_file_header *header;
132
133
struct splash_pic_priv *pics;
134
+
135
+ /*
136
+ * A local copy of the frame delay in the header.
137
+ * We modify it to keep the code simple.
138
+ */
139
+ u16 frame_ms;
140
};
141
142
143
@@ -71,6 +79,7 @@ struct splash_priv {
144
struct platform_device *splash_device;
145
146
struct work_struct work_redraw_vc;
147
+ struct delayed_work dwork_animation;
148
149
/* Splash data structures including lock for everything below */
150
struct mutex data_lock;
151
@@ -88,8 +97,10 @@ struct splash_priv {
152
void bootsplash_do_render_background(struct fb_info *info,
153
const struct splash_file_priv *fp);
154
void bootsplash_do_render_pictures(struct fb_info *info,
155
- const struct splash_file_priv *fp);
156
+ const struct splash_file_priv *fp,
157
+ bool is_update);
158
void bootsplash_do_render_flush(struct fb_info *info);
159
+void bootsplash_do_step_animations(struct splash_file_priv *fp);
160
161
162
void bootsplash_free_file(struct splash_file_priv *fp);
163
diff --git a/drivers/video/fbdev/core/bootsplash_load.c b/drivers/video/fbdev/core/bootsplash_load.c
164
index fd807571ab7d..1f661b2d4cc9 100644
165
--- a/drivers/video/fbdev/core/bootsplash_load.c
166
+++ b/drivers/video/fbdev/core/bootsplash_load.c
167
@@ -71,6 +71,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
168
{
169
const struct firmware *fw;
170
struct splash_file_priv *fp;
171
+ bool have_anim = false;
172
unsigned int i;
173
const u8 *walker;
174
175
@@ -135,6 +136,13 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
176
goto err;
177
}
178
179
+ if (ph->anim_type > SPLASH_ANIM_LOOP_FORWARD) {
180
+ pr_warn("Picture %u: Unsupported animation type %u.\n",
181
+ i, ph->anim_type);
182
+
183
+ ph->anim_type = SPLASH_ANIM_NONE;
184
+ }
185
+
186
pp->pic_header = ph;
187
pp->blobs = vzalloc(ph->num_blobs
188
* sizeof(struct splash_blob_priv));
189
@@ -202,6 +210,7 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
190
/* Walk over pictures and ensure all blob slots are filled */
191
for (i = 0; i < fp->header->num_pics; i++) {
192
struct splash_pic_priv *pp = &fp->pics[i];
193
+ const struct splash_pic_header *ph = pp->pic_header;
194
195
if (pp->blobs_loaded != pp->pic_header->num_blobs) {
196
pr_err("Picture %u doesn't have all blob slots filled.\n",
197
@@ -209,8 +218,20 @@ struct splash_file_priv *bootsplash_load_firmware(struct device *device,
198
199
goto err;
200
}
201
+
202
+ if (ph->anim_type
203
+ && ph->num_blobs > 1
204
+ && ph->anim_loop < pp->blobs_loaded)
205
+ have_anim = true;
206
}
207
208
+ if (!have_anim)
209
+ /* Disable animation timer if there is nothing to animate */
210
+ fp->frame_ms = 0;
211
+ else
212
+ /* Enforce minimum delay between frames */
213
+ fp->frame_ms = max((u16)20, fp->header->frame_ms);
214
+
215
pr_info("Loaded (%ld bytes, %u pics, %u blobs).\n",
216
fw->size,
217
fp->header->num_pics,
218
diff --git a/drivers/video/fbdev/core/bootsplash_render.c b/drivers/video/fbdev/core/bootsplash_render.c
219
index 07e3a4eab811..76033606ca8a 100644
220
--- a/drivers/video/fbdev/core/bootsplash_render.c
221
+++ b/drivers/video/fbdev/core/bootsplash_render.c
222
@@ -148,7 +148,8 @@ void bootsplash_do_render_background(struct fb_info *info,
223
224
225
void bootsplash_do_render_pictures(struct fb_info *info,
226
- const struct splash_file_priv *fp)
227
+ const struct splash_file_priv *fp,
228
+ bool is_update)
229
{
230
unsigned int i;
231
232
@@ -161,7 +162,11 @@ void bootsplash_do_render_pictures(struct fb_info *info,
233
if (pp->blobs_loaded < 1)
234
continue;
235
236
- bp = &pp->blobs[0];
237
+ /* Skip static pictures when refreshing animations */
238
+ if (ph->anim_type == SPLASH_ANIM_NONE && is_update)
239
+ continue;
240
+
241
+ bp = &pp->blobs[pp->anim_nextframe];
242
243
if (!bp || bp->blob_header->type != 0)
244
continue;
245
@@ -351,3 +356,24 @@ void bootsplash_do_render_flush(struct fb_info *info)
246
info->fbops->fb_copyarea(info, &area);
247
}
248
}
249
+
250
+
251
+void bootsplash_do_step_animations(struct splash_file_priv *fp)
252
+{
253
+ unsigned int i;
254
+
255
+ /* Step every animation once */
256
+ for (i = 0; i < fp->header->num_pics; i++) {
257
+ struct splash_pic_priv *pp = &fp->pics[i];
258
+
259
+ if (pp->blobs_loaded < 2
260
+ || pp->pic_header->anim_loop > pp->blobs_loaded)
261
+ continue;
262
+
263
+ if (pp->pic_header->anim_type == SPLASH_ANIM_LOOP_FORWARD) {
264
+ pp->anim_nextframe++;
265
+ if (pp->anim_nextframe >= pp->pic_header->num_blobs)
266
+ pp->anim_nextframe = pp->pic_header->anim_loop;
267
+ }
268
+ }
269
+}
270
diff --git a/include/uapi/linux/bootsplash_file.h b/include/uapi/linux/bootsplash_file.h
271
index 71cedcc68933..b3af0a3c6487 100644
272
--- a/include/uapi/linux/bootsplash_file.h
273
+++ b/include/uapi/linux/bootsplash_file.h
274
@@ -77,7 +77,17 @@ struct splash_file_header {
275
uint16_t num_blobs;
276
uint8_t num_pics;
277
278
- uint8_t padding[103];
279
+ uint8_t unused_1;
280
+
281
+ /*
282
+ * Milliseconds to wait before painting the next frame in
283
+ * an animation.
284
+ * This is actually a minimum, as the system is allowed to
285
+ * stall for longer between frames.
286
+ */
287
+ uint16_t frame_ms;
288
+
289
+ uint8_t padding[100];
290
} __attribute__((__packed__));
291
292
293
@@ -116,7 +126,23 @@ struct splash_pic_header {
294
*/
295
uint16_t position_offset;
296
297
- uint8_t padding[24];
298
+ /*
299
+ * Animation type.
300
+ * 0 - off
301
+ * 1 - forward loop
302
+ */
303
+ uint8_t anim_type;
304
+
305
+ /*
306
+ * Animation loop point.
307
+ * Actual meaning depends on animation type:
308
+ * Type 0 - Unused
309
+ * 1 - Frame at which to restart the forward loop
310
+ * (allowing for "intro" frames)
311
+ */
312
+ uint8_t anim_loop;
313
+
314
+ uint8_t padding[22];
315
} __attribute__((__packed__));
316
317
318
@@ -158,4 +184,9 @@ enum splash_position {
319
SPLASH_POS_FLAG_CORNER = 0x10,
320
};
321
322
+enum splash_anim_type {
323
+ SPLASH_ANIM_NONE = 0,
324
+ SPLASH_ANIM_LOOP_FORWARD = 1,
325
+};
326
+
327
#endif
328
329