1 /* $NetBSD: splash.c,v 1.6 2008/05/10 15:31:05 martin Exp $ */
4 * Copyright (c) 2006 Jared D. McNeill <jmcneill@invisible.ca>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the NetBSD
18 * Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: splash.c,v 1.6 2008/05/10 15:31:05 martin Exp $");
39 #include "opt_splash.h"
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/types.h>
49 #include <sys/kernel.h>
50 #include <sys/kthread.h>
52 #include <dev/splash/splash.h>
54 #if !defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
55 #error "options SPLASHSCREEN_PROGRESS requires SPLASHSCREEN"
58 #ifdef __HAVE_CPU_COUNTER
60 #include <machine/cpu_counter.h>
63 #ifndef SPLASHSCREEN_IMAGE
64 #define SPLASHSCREEN_IMAGE "dev/splash/images/netbsd.h"
68 #include SPLASHSCREEN_IMAGE
70 #ifdef SPLASHSCREEN_PROGRESS
71 struct splash_progress
*splash_progress_state
;
72 #ifdef __HAVE_CPU_COUNTER
73 static uint64_t splash_last_update
;
78 static void splash_render8(struct splash_info
*, const char *, int,
82 static void splash_render16(struct splash_info
*, const char *, int,
86 static void splash_render32(struct splash_info
*, const char *, int,
91 splash_render(struct splash_info
*si
, int flg
)
96 if (flg
& SPLASH_F_CENTER
) {
97 xoff
= (si
->si_width
- _splash_width
) / 2;
98 yoff
= (si
->si_height
- _splash_height
) / 2;
102 switch (si
->si_depth
) {
105 splash_render8(si
, _splash_header_data
, xoff
, yoff
,
106 _splash_width
, _splash_height
, flg
);
111 splash_render16(si
, _splash_header_data
, xoff
, yoff
,
112 _splash_width
, _splash_height
, flg
);
117 splash_render32(si
, _splash_header_data
, xoff
, yoff
,
118 _splash_width
, _splash_height
, flg
);
122 aprint_error("WARNING: Splash not supported at %dbpp\n",
132 splash_render8(struct splash_info
*si
, const char *data
, int xoff
, int yoff
,
133 int swidth
, int sheight
, int flg
)
141 if (flg
& SPLASH_F_FILL
)
147 fb
+= xoff
+ (yoff
* si
->si_width
);
148 for (y
= 0; y
< sheight
; y
++) {
149 for (x
= 0; x
< swidth
; x
++) {
151 pix
+= SPLASH_CMAP_OFFSET
;
153 for (i
= 0; i
< (si
->si_width
* si
->si_height
);
155 si
->si_bits
[i
] = pix
;
163 /* If we've just written to the shadow fb, copy it to the display */
165 if (flg
& SPLASH_F_FILL
) {
166 memcpy(si
->si_hwbits
, si
->si_bits
,
167 si
->si_width
*si
->si_height
);
171 rp
= si
->si_bits
+ xoff
+ (yoff
* si
->si_width
);
172 hrp
= si
->si_hwbits
+ xoff
+ (yoff
* si
->si_width
);
174 for (y
= 0; y
< sheight
; y
++) {
175 memcpy(hrp
, rp
, swidth
);
176 hrp
+= si
->si_stride
;
184 #endif /* !NSPLASH8 > 0 */
187 #define RGBTO16(b, o, x, c) \
189 uint16_t *_ptr = (uint16_t *)(&(b)[(o)]); \
190 *_ptr = (((c)[(x)*3+0] / 8) << 11) | \
191 (((c)[(x)*3+1] / 4) << 5) | \
192 (((c)[(x)*3+2] / 8) << 0); \
196 splash_render16(struct splash_info
*si
, const char *data
, int xoff
, int yoff
,
197 int swidth
, int sheight
, int flg
)
207 if (flg
& SPLASH_F_FILL
)
213 fb
+= xoff
* 2 + yoff
* si
->si_stride
;
215 for (y
= 0; y
< sheight
; y
++) {
216 for (x
= 0; x
< swidth
; x
++) {
217 _SPLASH_HEADER_PIXEL(d
, pix
);
221 while (i
< si
->si_height
*si
->si_stride
) {
222 RGBTO16(p
, i
, 0, pix
);
227 RGBTO16(fb
, x
*2, 0, pix
);
232 /* If we've just written to the shadow fb, copy it to the display */
234 if (flg
& SPLASH_F_FILL
) {
235 memcpy(si
->si_hwbits
, si
->si_bits
,
236 si
->si_height
*si
->si_stride
);
240 rp
= si
->si_bits
+ (xoff
* 2) + (yoff
* si
->si_stride
);
241 hrp
= si
->si_hwbits
+ (xoff
* 2) +
242 (yoff
* si
->si_stride
);
244 for (y
= 0; y
< sheight
; y
++) {
245 memcpy(hrp
, rp
, swidth
* 2);
247 hrp
+= si
->si_stride
;
255 #endif /* !NSPLASH16 > 0 */
259 splash_render32(struct splash_info
*si
, const char *data
, int xoff
, int yoff
,
260 int swidth
, int sheight
, int flg
)
270 if (flg
& SPLASH_F_FILL
)
276 fb
+= xoff
* 4 + yoff
* si
->si_stride
;
278 for (y
= 0; y
< sheight
; y
++) {
279 for (x
= 0; x
< swidth
; x
++) {
280 _SPLASH_HEADER_PIXEL(d
, pix
);
284 while (i
< si
->si_height
*si
->si_stride
) {
300 /* If we've just written to the shadow fb, copy it to the display */
302 if (flg
& SPLASH_F_FILL
) {
303 memcpy(si
->si_hwbits
, si
->si_bits
,
304 si
->si_height
*si
->si_stride
);
308 rp
= si
->si_bits
+ (xoff
* 4) + (yoff
* si
->si_stride
);
309 hrp
= si
->si_hwbits
+ (xoff
* 4) +
310 (yoff
* si
->si_stride
);
312 for (y
= 0; y
< sheight
; y
++) {
313 memcpy(hrp
, rp
, swidth
* 4);
315 hrp
+= si
->si_stride
;
322 #endif /* !NSPLASH32 > 0 */
324 #ifdef SPLASHSCREEN_PROGRESS
327 splash_progress_render(struct splash_progress
*sp
)
329 struct splash_info
*si
;
340 /* where should we draw the pulsers? */
341 yoff
= (si
->si_height
/ 8) * 7;
342 w
= _pulse_off_width
* SPLASH_PROGRESS_NSTATES
;
343 xoff
= (si
->si_width
/ 4) * 3;
344 spacing
= _pulse_off_width
; /* XXX */
346 for (i
= 0; i
< SPLASH_PROGRESS_NSTATES
; i
++) {
347 const char *d
= (sp
->sp_state
== i
? _pulse_on_header_data
:
348 _pulse_off_header_data
);
349 switch (si
->si_depth
) {
352 splash_render8(si
, d
, (xoff
+ (i
* spacing
)),
353 yoff
, _pulse_off_width
, _pulse_off_height
, flg
);
358 splash_render16(si
, d
, (xoff
+ (i
* spacing
)),
359 yoff
, _pulse_off_width
, _pulse_off_height
, flg
);
364 splash_render32(si
, d
, (xoff
+ (i
* spacing
)),
365 yoff
, _pulse_off_width
, _pulse_off_height
, flg
);
376 splash_progress_stop(device_t dev
)
378 struct splash_progress
*sp
;
380 sp
= (struct splash_progress
*)dev
;
387 splash_progress_init(struct splash_progress
*sp
)
389 #ifdef __HAVE_CPU_COUNTER
390 if (cpu_hascounter())
391 splash_last_update
= cpu_counter();
393 splash_last_update
= 0;
398 splash_progress_state
= sp
;
399 splash_progress_render(sp
);
400 config_finalize_register((device_t
)sp
, splash_progress_stop
);
406 splash_progress_update(struct splash_progress
*sp
)
408 if (sp
->sp_running
== 0 && sp
->sp_force
== 0)
411 #ifdef __HAVE_CPU_COUNTER
412 if (cpu_hascounter()) {
415 if (splash_last_update
== 0) {
416 splash_last_update
= cpu_counter();
419 if (splash_last_update
+ cpu_frequency(curcpu())/4 >
422 splash_last_update
= now
;
427 if (sp
->sp_state
>= SPLASH_PROGRESS_NSTATES
)
430 splash_progress_render(sp
);
433 #endif /* !SPLASHSCREEN_PROGRESS */
435 #endif /* !SPLASHSCREEN */