| 1 |
diff --git a/Documentation/fb/00-INDEX b/Documentation/fb/00-INDEX |
| 2 |
index 92e89ae..a6cfacc 100644 |
| 3 |
--- a/Documentation/fb/00-INDEX |
| 4 |
+++ b/Documentation/fb/00-INDEX |
| 5 |
@@ -19,6 +19,8 @@ matroxfb.txt |
| 6 |
- info on the Matrox frame buffer driver |
| 7 |
pvr2fb.txt |
| 8 |
- info on the PowerVR 2 frame buffer driver |
| 9 |
+splash.txt |
| 10 |
+ - info on the Framebuffer Splash |
| 11 |
tgafb.txt |
| 12 |
- info on the TGA (DECChip 21030) frame buffer driver |
| 13 |
vesafb.txt |
| 14 |
diff --git a/Documentation/fb/splash.txt b/Documentation/fb/splash.txt |
| 15 |
new file mode 100644 |
| 16 |
index 0000000..5e3b009 |
| 17 |
--- /dev/null |
| 18 |
+++ b/Documentation/fb/splash.txt |
| 19 |
@@ -0,0 +1,207 @@ |
| 20 |
+What is it? |
| 21 |
+----------- |
| 22 |
+ |
| 23 |
+The framebuffer splash is a kernel feature that allows displaying a background |
| 24 |
+picture on selected consoles. |
| 25 |
+ |
| 26 |
+What do I need to get it to work? |
| 27 |
+--------------------------------- |
| 28 |
+ |
| 29 |
+To get fb splash up-and-running you will have to: |
| 30 |
+ 1) get a copy of splashutils [1] or a similar program |
| 31 |
+ 2) get some splash themes |
| 32 |
+ 3) build the kernel helper program |
| 33 |
+ 4) build your kernel with the FB_SPLASH option enabled. |
| 34 |
+ |
| 35 |
+To get fb splash operational right after fbcon initialization is finished, you |
| 36 |
+will have to include a theme and the kernel helper into your initramfs image. |
| 37 |
+Please refer to splashutils documentation for instructions on how to do that. |
| 38 |
+ |
| 39 |
+[1] The splashutils package can be downloaded from: |
| 40 |
+ http://dev.gentoo.org/~spock/projects/splashutils/ |
| 41 |
+ |
| 42 |
+The userspace helper |
| 43 |
+-------------------- |
| 44 |
+ |
| 45 |
+The userspace splash helper (by default: /sbin/splash_helper) is called by the |
| 46 |
+kernel whenever an important event occurs and the kernel needs some kind of |
| 47 |
+job to be carried out. Important events include console switches and graphic |
| 48 |
+mode switches (the kernel requests background images and configuration |
| 49 |
+parameters for the current console). The splash helper must be accessible at |
| 50 |
+all times. If it's not, fbsplash will be switched off automatically. |
| 51 |
+ |
| 52 |
+It's possible to set path to the splash helper by writing it to |
| 53 |
+/proc/sys/kernel/fbsplash. |
| 54 |
+ |
| 55 |
+***************************************************************************** |
| 56 |
+ |
| 57 |
+The information below is mostly technical stuff. There's probably no need to |
| 58 |
+read it unless you plan to develop a userspace helper. |
| 59 |
+ |
| 60 |
+The splash protocol |
| 61 |
+------------------- |
| 62 |
+ |
| 63 |
+The splash protocol defines a communication interface between the kernel and |
| 64 |
+the userspace splash helper. |
| 65 |
+ |
| 66 |
+The kernel side is responsible for: |
| 67 |
+ |
| 68 |
+ o rendering console text, using an image as a background (instead of a |
| 69 |
+ standard solid color fbcon uses), |
| 70 |
+ o accepting commands from the user via ioctls on the fbsplash device, |
| 71 |
+ o calling the userspace helper to set things up as soon as the fb subsystem |
| 72 |
+ is initialized. |
| 73 |
+ |
| 74 |
+The userspace helper is responsible for everything else, including parsing |
| 75 |
+configuration files, decompressing the image files whenever the kernel needs |
| 76 |
+it, and communicating with the kernel if necessary. |
| 77 |
+ |
| 78 |
+The splash protocol specifies how communication is done in both ways: |
| 79 |
+kernel->userspace and userspace->helper. |
| 80 |
+ |
| 81 |
+Kernel -> Userspace |
| 82 |
+------------------- |
| 83 |
+ |
| 84 |
+The kernel communicates with the userspace helper by calling it and specifying |
| 85 |
+the task to be done in a series of arguments. |
| 86 |
+ |
| 87 |
+The arguments follow the pattern: |
| 88 |
+<splash protocol version> <command> <parameters> |
| 89 |
+ |
| 90 |
+All commands defined in splash protocol v2 have the following parameters: |
| 91 |
+ virtual console |
| 92 |
+ framebuffer number |
| 93 |
+ theme |
| 94 |
+ |
| 95 |
+Splash protocol v1 specified an additional 'fbsplash mode' after the |
| 96 |
+framebuffer number. Splash protocol v1 is deprecated and should not be used. |
| 97 |
+ |
| 98 |
+Splash protocol v2 specifies the following commands: |
| 99 |
+ |
| 100 |
+getpic |
| 101 |
+------ |
| 102 |
+ The kernel issues this command to request image data. It's up to the userspace |
| 103 |
+ helper to find a background image appropriate for the specified theme and the |
| 104 |
+ current resolution. The userspace helper should respond by issuing the |
| 105 |
+ FBIOSPLASH_SETPIC ioctl. |
| 106 |
+ |
| 107 |
+init |
| 108 |
+---- |
| 109 |
+ The kernel issues this command after the fbsplash device is created and |
| 110 |
+ the fbsplash interface is initialized. Upon receiving 'init', the userspace |
| 111 |
+ helper should parse the kernel command line (/proc/cmdline) or otherwise |
| 112 |
+ decide whether fbsplash is to be activated. |
| 113 |
+ |
| 114 |
+ To activate fbsplash on the first console the helper should issue the |
| 115 |
+ FBIOSPLASH_SETCFG, FBIOSPLASH_SETPIC and FBIOSPLASH_SETSTATE commands, |
| 116 |
+ in the above-mentioned order. |
| 117 |
+ |
| 118 |
+ When the userspace helper is called in an early phase of the boot process |
| 119 |
+ (right after the initialization of fbcon), no filesystems will be mounted. |
| 120 |
+ The helper program should mount sysfs and then create the appropriate |
| 121 |
+ framebuffer, fbsplash and tty0 devices (if they don't already exist) to get |
| 122 |
+ current display settings and to be able to communicate with the kernel side. |
| 123 |
+ It should probably also mount the procfs to be able to parse the kernel |
| 124 |
+ command line parameters. |
| 125 |
+ |
| 126 |
+ Note that the console sem is not held when the kernel calls splash_helper |
| 127 |
+ with the 'init' command. The splash helper should perform all ioctls with |
| 128 |
+ origin set to FB_SPLASH_IO_ORIG_USER. |
| 129 |
+ |
| 130 |
+modechange |
| 131 |
+---------- |
| 132 |
+ The kernel issues this command on a mode change. The helper's response should |
| 133 |
+ be similar to the response to the 'init' command. Note that this time the |
| 134 |
+ console sem is held and all ioctls must be performed with origin set to |
| 135 |
+ FB_SPLASH_IO_ORIG_KERNEL. |
| 136 |
+ |
| 137 |
+ |
| 138 |
+Userspace -> Kernel |
| 139 |
+------------------- |
| 140 |
+ |
| 141 |
+Userspace programs can communicate with fbsplash via ioctls on the fbsplash |
| 142 |
+device. These ioctls are to be used by both the userspace helper (called |
| 143 |
+only by the kernel) and userspace configuration tools (run by the users). |
| 144 |
+ |
| 145 |
+The splash helper should set the origin field to FB_SPLASH_IO_ORIG_KERNEL |
| 146 |
+when doing the appropriate ioctls. All userspace configuration tools should |
| 147 |
+use FB_SPLASH_IO_ORIG_USER. Failure to set the appropriate value in the origin |
| 148 |
+field when performing ioctls from the kernel helper will most likely result |
| 149 |
+in a console deadlock. |
| 150 |
+ |
| 151 |
+FB_SPLASH_IO_ORIG_KERNEL instructs fbsplash not to try to acquire the console |
| 152 |
+semaphore. Not surprisingly, FB_SPLASH_IO_ORIG_USER instructs it to acquire |
| 153 |
+the console sem. |
| 154 |
+ |
| 155 |
+The framebuffer splash provides the following ioctls (all defined in |
| 156 |
+linux/fb.h): |
| 157 |
+ |
| 158 |
+FBIOSPLASH_SETPIC |
| 159 |
+description: loads a background picture for a virtual console |
| 160 |
+argument: struct fb_splash_iowrapper*; data: struct fb_image* |
| 161 |
+notes: |
| 162 |
+If called for consoles other than the current foreground one, the picture data |
| 163 |
+will be ignored. |
| 164 |
+ |
| 165 |
+If the current virtual console is running in a 8-bpp mode, the cmap substruct |
| 166 |
+of fb_image has to be filled appropriately: start should be set to 16 (first |
| 167 |
+16 colors are reserved for fbcon), len to a value <= 240 and red, green and |
| 168 |
+blue should point to valid cmap data. The transp field is ingored. The fields |
| 169 |
+dx, dy, bg_color, fg_color in fb_image are ignored as well. |
| 170 |
+ |
| 171 |
+FBIOSPLASH_SETCFG |
| 172 |
+description: sets the fbsplash config for a virtual console |
| 173 |
+argument: struct fb_splash_iowrapper*; data: struct vc_splash* |
| 174 |
+notes: The structure has to be filled with valid data. |
| 175 |
+ |
| 176 |
+FBIOSPLASH_GETCFG |
| 177 |
+description: gets the fbsplash config for a virtual console |
| 178 |
+argument: struct fb_splash_iowrapper*; data: struct vc_splash* |
| 179 |
+ |
| 180 |
+FBIOSPLASH_SETSTATE |
| 181 |
+description: sets the fbsplash state for a virtual console |
| 182 |
+argument: struct fb_splash_iowrapper*; data: unsigned int* |
| 183 |
+ values: 0 = disabled, 1 = enabled. |
| 184 |
+ |
| 185 |
+FBIOSPLASH_GETSTATE |
| 186 |
+description: gets the fbsplash state for a virtual console |
| 187 |
+argument: struct fb_splash_iowrapper*; data: unsigned int* |
| 188 |
+ values: as in FBIOSPLASH_SETSTATE |
| 189 |
+ |
| 190 |
+Info on used structures: |
| 191 |
+ |
| 192 |
+Definition of struct vc_splash can be found in linux/console_splash.h. It's |
| 193 |
+heavily commented. Note that the 'theme' field should point to a string |
| 194 |
+no longer than FB_SPLASH_THEME_LEN. When FBIOSPLASH_GETCFG call is |
| 195 |
+performed, the theme field should point to a char buffer of length |
| 196 |
+FB_SPLASH_THEME_LEN. |
| 197 |
+ |
| 198 |
+Definition of struct fb_splash_iowrapper can be found in linux/fb.h. |
| 199 |
+The fields in this struct have the following meaning: |
| 200 |
+ |
| 201 |
+vc: |
| 202 |
+Virtual console number. |
| 203 |
+ |
| 204 |
+origin: |
| 205 |
+Specifies if the ioctl is performed as a response to a kernel request. The |
| 206 |
+splash helper should set this field to FB_SPLASH_IO_ORIG_KERNEL, userspace |
| 207 |
+programs should set it to FB_SPLASH_IO_ORIG_USER. This field is necessary to |
| 208 |
+avoid console semaphore deadlocks. |
| 209 |
+ |
| 210 |
+data: |
| 211 |
+Pointer to a data structure appropriate for the performed ioctl. Type of |
| 212 |
+the data struct is specified in the ioctls description. |
| 213 |
+ |
| 214 |
+***************************************************************************** |
| 215 |
+ |
| 216 |
+Credit |
| 217 |
+------ |
| 218 |
+ |
| 219 |
+Original 'bootsplash' project & implementation by: |
| 220 |
+ Volker Poplawski <volker@poplawski.de>, Stefan Reinauer <stepan@suse.de>, |
| 221 |
+ Steffen Winterfeldt <snwint@suse.de>, Michael Schroeder <mls@suse.de>, |
| 222 |
+ Ken Wimer <wimer@suse.de>. |
| 223 |
+ |
| 224 |
+Fbsplash, splash protocol design, current implementation & docs by: |
| 225 |
+ Michael Januszewski <spock@gentoo.org> |
| 226 |
+ |
| 227 |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig |
| 228 |
index 25b6ca6..dac3de5 100644 |
| 229 |
--- a/drivers/video/Kconfig |
| 230 |
+++ b/drivers/video/Kconfig |
| 231 |
@@ -752,7 +752,6 @@ config FB_MATROX |
| 232 |
select FB_CFB_FILLRECT |
| 233 |
select FB_CFB_COPYAREA |
| 234 |
select FB_CFB_IMAGEBLIT |
| 235 |
- select FB_TILEBLITTING |
| 236 |
select FB_MACMODES if PPC_PMAC |
| 237 |
---help--- |
| 238 |
Say Y here if you have a Matrox Millennium, Matrox Millennium II, |
| 239 |
@@ -1468,5 +1467,15 @@ if FB && SYSFS |
| 240 |
source "drivers/video/backlight/Kconfig" |
| 241 |
endif |
| 242 |
|
| 243 |
-endmenu |
| 244 |
+config FB_SPLASH |
| 245 |
+ bool "Support for the framebuffer splash" |
| 246 |
+ depends on FRAMEBUFFER_CONSOLE=y && !FB_TILEBLITTING |
| 247 |
+ default n |
| 248 |
+ ---help--- |
| 249 |
+ This option enables support for the Linux boot-up splash screen and |
| 250 |
+ graphical backgrounds on consoles. Note that you will need userspace |
| 251 |
+ splash utilities in order to take advantage of these features. Refer |
| 252 |
+ to Documentation/fb/splash.txt for more information. |
| 253 |
|
| 254 |
+ If unsure, say N. |
| 255 |
+endmenu |
| 256 |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile |
| 257 |
index aa434e7..8a74fce 100644 |
| 258 |
--- a/drivers/video/Makefile |
| 259 |
+++ b/drivers/video/Makefile |
| 260 |
@@ -7,6 +7,7 @@ |
| 261 |
obj-$(CONFIG_VT) += console/ |
| 262 |
obj-$(CONFIG_LOGO) += logo/ |
| 263 |
obj-$(CONFIG_SYSFS) += backlight/ |
| 264 |
+obj-$(CONFIG_FB_SPLASH) += fbsplash.o cfbsplash.o |
| 265 |
|
| 266 |
obj-$(CONFIG_FB) += fb.o |
| 267 |
fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ |
| 268 |
diff --git a/drivers/video/cfbsplash.c b/drivers/video/cfbsplash.c |
| 269 |
new file mode 100644 |
| 270 |
index 0000000..4adeb2e |
| 271 |
--- /dev/null |
| 272 |
+++ b/drivers/video/cfbsplash.c |
| 273 |
@@ -0,0 +1,472 @@ |
| 274 |
+/* |
| 275 |
+ * linux/drivers/video/cfbsplash.c -- Framebuffer splash render functions |
| 276 |
+ * |
| 277 |
+ * Copyright (C) 2004 Michal Januszewski <spock@gentoo.org> |
| 278 |
+ * |
| 279 |
+ * Code based upon "Bootsplash" (C) 2001-2003 |
| 280 |
+ * Volker Poplawski <volker@poplawski.de>, |
| 281 |
+ * Stefan Reinauer <stepan@suse.de>, |
| 282 |
+ * Steffen Winterfeldt <snwint@suse.de>, |
| 283 |
+ * Michael Schroeder <mls@suse.de>, |
| 284 |
+ * Ken Wimer <wimer@suse.de>. |
| 285 |
+ * |
| 286 |
+ * This file is subject to the terms and conditions of the GNU General Public |
| 287 |
+ * License. See the file COPYING in the main directory of this archive for |
| 288 |
+ * more details. |
| 289 |
+ */ |
| 290 |
+#include <linux/config.h> |
| 291 |
+#include <linux/module.h> |
| 292 |
+#include <linux/types.h> |
| 293 |
+#include <linux/fb.h> |
| 294 |
+#include <linux/selection.h> |
| 295 |
+#include <linux/vt_kern.h> |
| 296 |
+#include <asm/irq.h> |
| 297 |
+#include <asm/system.h> |
| 298 |
+ |
| 299 |
+#include "console/fbcon.h" |
| 300 |
+#include "fbsplash.h" |
| 301 |
+ |
| 302 |
+#define parse_pixel(shift,bpp,type) \ |
| 303 |
+ do { \ |
| 304 |
+ if (d & (0x80 >> (shift))) \ |
| 305 |
+ dd2[(shift)] = fgx; \ |
| 306 |
+ else \ |
| 307 |
+ dd2[(shift)] = transparent ? *(type *)splash_src : bgx; \ |
| 308 |
+ splash_src += (bpp); \ |
| 309 |
+ } while (0) \ |
| 310 |
+ |
| 311 |
+extern int get_color(struct vc_data *vc, struct fb_info *info, |
| 312 |
+ u16 c, int is_fg); |
| 313 |
+ |
| 314 |
+void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) |
| 315 |
+{ |
| 316 |
+ int i, j, k; |
| 317 |
+ int minlen = min(min(info->var.red.length, info->var.green.length), |
| 318 |
+ info->var.blue.length); |
| 319 |
+ u32 col; |
| 320 |
+ |
| 321 |
+ for (j = i = 0; i < 16; i++) { |
| 322 |
+ k = color_table[i]; |
| 323 |
+ |
| 324 |
+ col = ((vc->vc_palette[j++] >> (8-minlen)) |
| 325 |
+ << info->var.red.offset); |
| 326 |
+ col |= ((vc->vc_palette[j++] >> (8-minlen)) |
| 327 |
+ << info->var.green.offset); |
| 328 |
+ col |= ((vc->vc_palette[j++] >> (8-minlen)) |
| 329 |
+ << info->var.blue.offset); |
| 330 |
+ ((u32 *)info->pseudo_palette)[k] = col; |
| 331 |
+ } |
| 332 |
+} |
| 333 |
+ |
| 334 |
+void fbsplash_renderc(struct fb_info *info, int ypos, int xpos, int height, |
| 335 |
+ int width, u8* src, u32 fgx, u32 bgx, u8 transparent) |
| 336 |
+{ |
| 337 |
+ unsigned int x, y; |
| 338 |
+ u32 dd; |
| 339 |
+ int bytespp = ((info->var.bits_per_pixel + 7) >> 3); |
| 340 |
+ unsigned int d = ypos * info->fix.line_length + xpos * bytespp; |
| 341 |
+ unsigned int ds = (ypos * info->var.xres + xpos) * bytespp; |
| 342 |
+ u16 dd2[4]; |
| 343 |
+ |
| 344 |
+ u8* splash_src = (u8 *)(info->splash.data + ds); |
| 345 |
+ u8* dst = (u8 *)(info->screen_base + d); |
| 346 |
+ |
| 347 |
+ if ((ypos + height) > info->var.yres || (xpos + width) > info->var.xres) |
| 348 |
+ return; |
| 349 |
+ |
| 350 |
+ for (y = 0; y < height; y++) { |
| 351 |
+ switch (info->var.bits_per_pixel) { |
| 352 |
+ |
| 353 |
+ case 32: |
| 354 |
+ for (x = 0; x < width; x++) { |
| 355 |
+ |
| 356 |
+ if ((x & 7) == 0) |
| 357 |
+ d = *src++; |
| 358 |
+ if (d & 0x80) |
| 359 |
+ dd = fgx; |
| 360 |
+ else |
| 361 |
+ dd = transparent ? |
| 362 |
+ *(u32 *)splash_src : bgx; |
| 363 |
+ |
| 364 |
+ d <<= 1; |
| 365 |
+ splash_src += 4; |
| 366 |
+ fb_writel(dd, dst); |
| 367 |
+ dst += 4; |
| 368 |
+ } |
| 369 |
+ break; |
| 370 |
+ case 24: |
| 371 |
+ for (x = 0; x < width; x++) { |
| 372 |
+ |
| 373 |
+ if ((x & 7) == 0) |
| 374 |
+ d = *src++; |
| 375 |
+ if (d & 0x80) |
| 376 |
+ dd = fgx; |
| 377 |
+ else |
| 378 |
+ dd = transparent ? |
| 379 |
+ (*(u32 *)splash_src & 0xffffff) : bgx; |
| 380 |
+ |
| 381 |
+ d <<= 1; |
| 382 |
+ splash_src += 3; |
| 383 |
+#ifdef __LITTLE_ENDIAN |
| 384 |
+ fb_writew(dd & 0xffff, dst); |
| 385 |
+ dst += 2; |
| 386 |
+ fb_writeb((dd >> 16), dst); |
| 387 |
+#else |
| 388 |
+ fb_writew(dd >> 8, dst); |
| 389 |
+ dst += 2; |
| 390 |
+ fb_writeb(dd & 0xff, dst); |
| 391 |
+#endif |
| 392 |
+ dst++; |
| 393 |
+ } |
| 394 |
+ break; |
| 395 |
+ case 16: |
| 396 |
+ for (x = 0; x < width; x += 2) { |
| 397 |
+ if ((x & 7) == 0) |
| 398 |
+ d = *src++; |
| 399 |
+ |
| 400 |
+ parse_pixel(0, 2, u16); |
| 401 |
+ parse_pixel(1, 2, u16); |
| 402 |
+#ifdef __LITTLE_ENDIAN |
| 403 |
+ dd = dd2[0] | (dd2[1] << 16); |
| 404 |
+#else |
| 405 |
+ dd = dd2[1] | (dd2[0] << 16); |
| 406 |
+#endif |
| 407 |
+ d <<= 2; |
| 408 |
+ fb_writel(dd, dst); |
| 409 |
+ dst += 4; |
| 410 |
+ } |
| 411 |
+ break; |
| 412 |
+ |
| 413 |
+ case 8: |
| 414 |
+ for (x = 0; x < width; x += 4) { |
| 415 |
+ if ((x & 7) == 0) |
| 416 |
+ d = *src++; |
| 417 |
+ |
| 418 |
+ parse_pixel(0, 1, u8); |
| 419 |
+ parse_pixel(1, 1, u8); |
| 420 |
+ parse_pixel(2, 1, u8); |
| 421 |
+ parse_pixel(3, 1, u8); |
| 422 |
+ |
| 423 |
+#ifdef __LITTLE_ENDIAN |
| 424 |
+ dd = dd2[0] | (dd2[1] << 8) | (dd2[2] << 16) | (dd2[3] << 24); |
| 425 |
+#else |
| 426 |
+ dd = dd2[3] | (dd2[2] << 8) | (dd2[1] << 16) | (dd2[0] << 24); |
| 427 |
+#endif |
| 428 |
+ d <<= 4; |
| 429 |
+ fb_writel(dd, dst); |
| 430 |
+ dst += 4; |
| 431 |
+ } |
| 432 |
+ } |
| 433 |
+ |
| 434 |
+ dst += info->fix.line_length - width * bytespp; |
| 435 |
+ splash_src += (info->var.xres - width) * bytespp; |
| 436 |
+ } |
| 437 |
+} |
| 438 |
+ |
| 439 |
+#define cc2cx(a) \ |
| 440 |
+ ((info->fix.visual == FB_VISUAL_TRUECOLOR || \ |
| 441 |
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) ? \ |
| 442 |
+ ((u32*)info->pseudo_palette)[a] : a) |
| 443 |
+ |
| 444 |
+void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, |
| 445 |
+ const unsigned short *s, int count, int yy, int xx) |
| 446 |
+{ |
| 447 |
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; |
| 448 |
+ struct fbcon_ops *ops = info->fbcon_par; |
| 449 |
+ int fg_color, bg_color, transparent; |
| 450 |
+ u8 *src; |
| 451 |
+ u32 bgx, fgx; |
| 452 |
+ u16 c = scr_readw(s); |
| 453 |
+ |
| 454 |
+ fg_color = get_color(vc, info, c, 1); |
| 455 |
+ bg_color = get_color(vc, info, c, 0); |
| 456 |
+ |
| 457 |
+ /* Don't paint the background image if console is blanked */ |
| 458 |
+ transparent = ops->blank_state ? 0 : |
| 459 |
+ (vc->vc_splash.bg_color == bg_color); |
| 460 |
+ |
| 461 |
+ xx = xx * vc->vc_font.width + vc->vc_splash.tx; |
| 462 |
+ yy = yy * vc->vc_font.height + vc->vc_splash.ty; |
| 463 |
+ |
| 464 |
+ fgx = cc2cx(fg_color); |
| 465 |
+ bgx = cc2cx(bg_color); |
| 466 |
+ |
| 467 |
+ while (count--) { |
| 468 |
+ c = scr_readw(s++); |
| 469 |
+ src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * |
| 470 |
+ ((vc->vc_font.width + 7) >> 3); |
| 471 |
+ |
| 472 |
+ fbsplash_renderc(info, yy, xx, vc->vc_font.height, |
| 473 |
+ vc->vc_font.width, src, fgx, bgx, transparent); |
| 474 |
+ xx += vc->vc_font.width; |
| 475 |
+ } |
| 476 |
+} |
| 477 |
+ |
| 478 |
+void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor) |
| 479 |
+{ |
| 480 |
+ int i; |
| 481 |
+ unsigned int dsize, s_pitch; |
| 482 |
+ struct fbcon_ops *ops = info->fbcon_par; |
| 483 |
+ struct vc_data* vc; |
| 484 |
+ u8 *src; |
| 485 |
+ |
| 486 |
+ /* we really don't need any cursors while the console is blanked */ |
| 487 |
+ if (info->state != FBINFO_STATE_RUNNING || ops->blank_state) |
| 488 |
+ return; |
| 489 |
+ |
| 490 |
+ vc = vc_cons[ops->currcon].d; |
| 491 |
+ |
| 492 |
+ src = kmalloc(64 + sizeof(struct fb_image), GFP_ATOMIC); |
| 493 |
+ if (!src) |
| 494 |
+ return; |
| 495 |
+ |
| 496 |
+ s_pitch = (cursor->image.width + 7) >> 3; |
| 497 |
+ dsize = s_pitch * cursor->image.height; |
| 498 |
+ if (cursor->enable) { |
| 499 |
+ switch (cursor->rop) { |
| 500 |
+ case ROP_XOR: |
| 501 |
+ for (i = 0; i < dsize; i++) |
| 502 |
+ src[i] = cursor->image.data[i] ^ cursor->mask[i]; |
| 503 |
+ break; |
| 504 |
+ case ROP_COPY: |
| 505 |
+ default: |
| 506 |
+ for (i = 0; i < dsize; i++) |
| 507 |
+ src[i] = cursor->image.data[i] & cursor->mask[i]; |
| 508 |
+ break; |
| 509 |
+ } |
| 510 |
+ } else |
| 511 |
+ memcpy(src, cursor->image.data, dsize); |
| 512 |
+ |
| 513 |
+ fbsplash_renderc(info, |
| 514 |
+ cursor->image.dy + vc->vc_splash.ty, |
| 515 |
+ cursor->image.dx + vc->vc_splash.tx, |
| 516 |
+ cursor->image.height, |
| 517 |
+ cursor->image.width, |
| 518 |
+ (u8*)src, |
| 519 |
+ cc2cx(cursor->image.fg_color), |
| 520 |
+ cc2cx(cursor->image.bg_color), |
| 521 |
+ cursor->image.bg_color == vc->vc_splash.bg_color); |
| 522 |
+ |
| 523 |
+ kfree(src); |
| 524 |
+} |
| 525 |
+ |
| 526 |
+static void splashset(u8 *dst, int height, int width, int dstbytes, |
| 527 |
+ u32 bgx, int bpp) |
| 528 |
+{ |
| 529 |
+ int i; |
| 530 |
+ |
| 531 |
+ if (bpp == 8) |
| 532 |
+ bgx |= bgx << 8; |
| 533 |
+ if (bpp == 16 || bpp == 8) |
| 534 |
+ bgx |= bgx << 16; |
| 535 |
+ |
| 536 |
+ while (height-- > 0) { |
| 537 |
+ u8 *p = dst; |
| 538 |
+ |
| 539 |
+ switch (bpp) { |
| 540 |
+ |
| 541 |
+ case 32: |
| 542 |
+ for (i=0; i < width; i++) { |
| 543 |
+ fb_writel(bgx, p); p += 4; |
| 544 |
+ } |
| 545 |
+ break; |
| 546 |
+ case 24: |
| 547 |
+ for (i=0; i < width; i++) { |
| 548 |
+#ifdef __LITTLE_ENDIAN |
| 549 |
+ fb_writew((bgx & 0xffff),(u16*)p); p += 2; |
| 550 |
+ fb_writeb((bgx >> 16),p++); |
| 551 |
+#else |
| 552 |
+ fb_writew((bgx >> 8),(u16*)p); p += 2; |
| 553 |
+ fb_writeb((bgx & 0xff),p++); |
| 554 |
+#endif |
| 555 |
+ } |
| 556 |
+ case 16: |
| 557 |
+ for (i=0; i < width/4; i++) { |
| 558 |
+ fb_writel(bgx,p); p += 4; |
| 559 |
+ fb_writel(bgx,p); p += 4; |
| 560 |
+ } |
| 561 |
+ if (width & 2) { |
| 562 |
+ fb_writel(bgx,p); p += 4; |
| 563 |
+ } |
| 564 |
+ if (width & 1) |
| 565 |
+ fb_writew(bgx,(u16*)p); |
| 566 |
+ break; |
| 567 |
+ case 8: |
| 568 |
+ for (i=0; i < width/4; i++) { |
| 569 |
+ fb_writel(bgx,p); p += 4; |
| 570 |
+ } |
| 571 |
+ |
| 572 |
+ if (width & 2) { |
| 573 |
+ fb_writew(bgx,p); p += 2; |
| 574 |
+ } |
| 575 |
+ if (width & 1) |
| 576 |
+ fb_writeb(bgx,(u8*)p); |
| 577 |
+ break; |
| 578 |
+ |
| 579 |
+ } |
| 580 |
+ dst += dstbytes; |
| 581 |
+ } |
| 582 |
+} |
| 583 |
+ |
| 584 |
+void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes, |
| 585 |
+ int srclinebytes, int bpp) |
| 586 |
+{ |
| 587 |
+ int i; |
| 588 |
+ |
| 589 |
+ while (height-- > 0) { |
| 590 |
+ u32 *p = (u32 *)dst; |
| 591 |
+ u32 *q = (u32 *)src; |
| 592 |
+ |
| 593 |
+ switch (bpp) { |
| 594 |
+ |
| 595 |
+ case 32: |
| 596 |
+ for (i=0; i < width; i++) |
| 597 |
+ fb_writel(*q++, p++); |
| 598 |
+ break; |
| 599 |
+ case 24: |
| 600 |
+ for (i=0; i < (width*3/4); i++) |
| 601 |
+ fb_writel(*q++, p++); |
| 602 |
+ if ((width*3) % 4) { |
| 603 |
+ if (width & 2) { |
| 604 |
+ fb_writeb(*(u8*)q, (u8*)p); |
| 605 |
+ } else if (width & 1) { |
| 606 |
+ fb_writew(*(u16*)q, (u16*)p); |
| 607 |
+ fb_writeb(*(u8*)((u16*)q+1),(u8*)((u16*)p+2)); |
| 608 |
+ } |
| 609 |
+ } |
| 610 |
+ break; |
| 611 |
+ case 16: |
| 612 |
+ for (i=0; i < width/4; i++) { |
| 613 |
+ fb_writel(*q++, p++); |
| 614 |
+ fb_writel(*q++, p++); |
| 615 |
+ } |
| 616 |
+ if (width & 2) |
| 617 |
+ fb_writel(*q++, p++); |
| 618 |
+ if (width & 1) |
| 619 |
+ fb_writew(*(u16*)q, (u16*)p); |
| 620 |
+ break; |
| 621 |
+ case 8: |
| 622 |
+ for (i=0; i < width/4; i++) |
| 623 |
+ fb_writel(*q++, p++); |
| 624 |
+ |
| 625 |
+ if (width & 2) { |
| 626 |
+ fb_writew(*(u16*)q, (u16*)p); |
| 627 |
+ q = (u32*) ((u16*)q + 1); |
| 628 |
+ p = (u32*) ((u16*)p + 1); |
| 629 |
+ } |
| 630 |
+ if (width & 1) |
| 631 |
+ fb_writeb(*(u8*)q, (u8*)p); |
| 632 |
+ break; |
| 633 |
+ } |
| 634 |
+ |
| 635 |
+ dst += linebytes; |
| 636 |
+ src += srclinebytes; |
| 637 |
+ } |
| 638 |
+} |
| 639 |
+ |
| 640 |
+static void splashfill(struct fb_info *info, int sy, int sx, int height, |
| 641 |
+ int width) |
| 642 |
+{ |
| 643 |
+ int bytespp = ((info->var.bits_per_pixel + 7) >> 3); |
| 644 |
+ int d = sy * info->fix.line_length + sx * bytespp; |
| 645 |
+ int ds = (sy * info->var.xres + sx) * bytespp; |
| 646 |
+ |
| 647 |
+ fbsplash_copy((u8 *)(info->screen_base + d), (u8 *)(info->splash.data + ds), |
| 648 |
+ height, width, info->fix.line_length, info->var.xres * bytespp, |
| 649 |
+ info->var.bits_per_pixel); |
| 650 |
+} |
| 651 |
+ |
| 652 |
+void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, |
| 653 |
+ int height, int width) |
| 654 |
+{ |
| 655 |
+ int bgshift = (vc->vc_hi_font_mask) ? 13 : 12; |
| 656 |
+ int bg_color = attr_bgcol_ec(bgshift, vc); |
| 657 |
+ int transparent = vc->vc_splash.bg_color == bg_color; |
| 658 |
+ struct fbcon_ops *ops = info->fbcon_par; |
| 659 |
+ u8 *dst; |
| 660 |
+ |
| 661 |
+ sy = sy * vc->vc_font.height + vc->vc_splash.ty; |
| 662 |
+ sx = sx * vc->vc_font.width + vc->vc_splash.tx; |
| 663 |
+ height *= vc->vc_font.height; |
| 664 |
+ width *= vc->vc_font.width; |
| 665 |
+ |
| 666 |
+ /* Don't paint the background image if console is blanked */ |
| 667 |
+ if (transparent && !ops->blank_state) { |
| 668 |
+ splashfill(info, sy, sx, height, width); |
| 669 |
+ } else { |
| 670 |
+ dst = (u8 *)(info->screen_base + sy * info->fix.line_length + |
| 671 |
+ sx * ((info->var.bits_per_pixel + 7) >> 3)); |
| 672 |
+ splashset(dst, height, width, info->fix.line_length, cc2cx(bg_color), |
| 673 |
+ info->var.bits_per_pixel); |
| 674 |
+ } |
| 675 |
+} |
| 676 |
+ |
| 677 |
+void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, |
| 678 |
+ int bottom_only) |
| 679 |
+{ |
| 680 |
+ unsigned int tw = vc->vc_cols*vc->vc_font.width; |
| 681 |
+ unsigned int th = vc->vc_rows*vc->vc_font.height; |
| 682 |
+ |
| 683 |
+ if (!bottom_only) { |
| 684 |
+ /* top margin */ |
| 685 |
+ splashfill(info, 0, 0, vc->vc_splash.ty, info->var.xres); |
| 686 |
+ /* left margin */ |
| 687 |
+ splashfill(info, vc->vc_splash.ty, 0, th, vc->vc_splash.tx); |
| 688 |
+ /* right margin */ |
| 689 |
+ splashfill(info, vc->vc_splash.ty, vc->vc_splash.tx + tw, th, |
| 690 |
+ info->var.xres - vc->vc_splash.tx - tw); |
| 691 |
+ } |
| 692 |
+ splashfill(info, vc->vc_splash.ty + th, 0, |
| 693 |
+ info->var.yres - vc->vc_splash.ty - th, info->var.xres); |
| 694 |
+} |
| 695 |
+ |
| 696 |
+void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, |
| 697 |
+ int sx, int dx, int width) |
| 698 |
+{ |
| 699 |
+ u16 *d = (u16 *) (vc->vc_origin + vc->vc_size_row * y + dx * 2); |
| 700 |
+ u16 *s = d + (dx - sx); |
| 701 |
+ u16 *start = d; |
| 702 |
+ u16 *ls = d; |
| 703 |
+ u16 *le = d + width; |
| 704 |
+ u16 c; |
| 705 |
+ int x = dx; |
| 706 |
+ u16 attr = 1; |
| 707 |
+ |
| 708 |
+ do { |
| 709 |
+ c = scr_readw(d); |
| 710 |
+ if (attr != (c & 0xff00)) { |
| 711 |
+ attr = c & 0xff00; |
| 712 |
+ if (d > start) { |
| 713 |
+ fbsplash_putcs(vc, info, start, d - start, y, x); |
| 714 |
+ x += d - start; |
| 715 |
+ start = d; |
| 716 |
+ } |
| 717 |
+ } |
| 718 |
+ if (s >= ls && s < le && c == scr_readw(s)) { |
| 719 |
+ if (d > start) { |
| 720 |
+ fbsplash_putcs(vc, info, start, d - start, y, x); |
| 721 |
+ x += d - start + 1; |
| 722 |
+ start = d + 1; |
| 723 |
+ } else { |
| 724 |
+ x++; |
| 725 |
+ start++; |
| 726 |
+ } |
| 727 |
+ } |
| 728 |
+ s++; |
| 729 |
+ d++; |
| 730 |
+ } while (d < le); |
| 731 |
+ if (d > start) |
| 732 |
+ fbsplash_putcs(vc, info, start, d - start, y, x); |
| 733 |
+} |
| 734 |
+ |
| 735 |
+void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank) |
| 736 |
+{ |
| 737 |
+ if (blank) { |
| 738 |
+ splashset((u8 *)info->screen_base, info->var.yres, info->var.xres, |
| 739 |
+ info->fix.line_length, 0, info->var.bits_per_pixel); |
| 740 |
+ } else { |
| 741 |
+ update_screen(vc); |
| 742 |
+ fbsplash_clear_margins(vc, info, 0); |
| 743 |
+ } |
| 744 |
+} |
| 745 |
+ |
| 746 |
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c |
| 747 |
index e65fc3e..b8fcb6e 100644 |
| 748 |
--- a/drivers/video/console/bitblit.c |
| 749 |
+++ b/drivers/video/console/bitblit.c |
| 750 |
@@ -18,6 +18,7 @@ |
| 751 |
#include <linux/console.h> |
| 752 |
#include <asm/types.h> |
| 753 |
#include "fbcon.h" |
| 754 |
+#include "../fbsplash.h" |
| 755 |
|
| 756 |
/* |
| 757 |
* Accelerated handlers. |
| 758 |
@@ -55,6 +56,13 @@ static void bit_bmove(struct vc_data *vc |
| 759 |
area.height = height * vc->vc_font.height; |
| 760 |
area.width = width * vc->vc_font.width; |
| 761 |
|
| 762 |
+ if (fbsplash_active(info, vc)) { |
| 763 |
+ area.sx += vc->vc_splash.tx; |
| 764 |
+ area.sy += vc->vc_splash.ty; |
| 765 |
+ area.dx += vc->vc_splash.tx; |
| 766 |
+ area.dy += vc->vc_splash.ty; |
| 767 |
+ } |
| 768 |
+ |
| 769 |
info->fbops->fb_copyarea(info, &area); |
| 770 |
} |
| 771 |
|
| 772 |
@@ -380,11 +388,15 @@ static void bit_cursor(struct vc_data *v |
| 773 |
cursor.image.depth = 1; |
| 774 |
cursor.rop = ROP_XOR; |
| 775 |
|
| 776 |
- if (info->fbops->fb_cursor) |
| 777 |
- err = info->fbops->fb_cursor(info, &cursor); |
| 778 |
+ if (fbsplash_active(info, vc)) { |
| 779 |
+ fbsplash_cursor(info, &cursor); |
| 780 |
+ } else { |
| 781 |
+ if (info->fbops->fb_cursor) |
| 782 |
+ err = info->fbops->fb_cursor(info, &cursor); |
| 783 |
|
| 784 |
- if (err) |
| 785 |
- soft_cursor(info, &cursor); |
| 786 |
+ if (err) |
| 787 |
+ soft_cursor(info, &cursor); |
| 788 |
+ } |
| 789 |
|
| 790 |
ops->cursor_reset = 0; |
| 791 |
} |
| 792 |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c |
| 793 |
index e7802ff..eeddc61 100644 |
| 794 |
--- a/drivers/video/console/fbcon.c |
| 795 |
+++ b/drivers/video/console/fbcon.c |
| 796 |
@@ -93,6 +93,7 @@ |
| 797 |
#endif |
| 798 |
|
| 799 |
#include "fbcon.h" |
| 800 |
+#include "../fbsplash.h" |
| 801 |
|
| 802 |
#ifdef FBCONDEBUG |
| 803 |
# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) |
| 804 |
@@ -109,7 +110,7 @@ enum { |
| 805 |
struct display fb_display[MAX_NR_CONSOLES]; |
| 806 |
EXPORT_SYMBOL(fb_display); |
| 807 |
|
| 808 |
-static signed char con2fb_map[MAX_NR_CONSOLES]; |
| 809 |
+signed char con2fb_map[MAX_NR_CONSOLES]; |
| 810 |
static signed char con2fb_map_boot[MAX_NR_CONSOLES]; |
| 811 |
static int logo_height; |
| 812 |
static int logo_lines; |
| 813 |
@@ -299,7 +300,7 @@ static inline int fbcon_is_inactive(stru |
| 814 |
vc->vc_mode != KD_TEXT || ops->graphics); |
| 815 |
} |
| 816 |
|
| 817 |
-static inline int get_color(struct vc_data *vc, struct fb_info *info, |
| 818 |
+inline int get_color(struct vc_data *vc, struct fb_info *info, |
| 819 |
u16 c, int is_fg) |
| 820 |
{ |
| 821 |
int depth = fb_get_color_depth(&info->var, &info->fix); |
| 822 |
@@ -405,6 +406,7 @@ static void fb_flashcursor(void *private |
| 823 |
CM_ERASE : CM_DRAW; |
| 824 |
ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1), |
| 825 |
get_color(vc, info, c, 0)); |
| 826 |
+ |
| 827 |
release_console_sem(); |
| 828 |
} |
| 829 |
|
| 830 |
@@ -569,6 +571,8 @@ static int fbcon_takeover(int show_logo) |
| 831 |
info_idx = -1; |
| 832 |
} |
| 833 |
|
| 834 |
+ fbsplash_init(); |
| 835 |
+ |
| 836 |
return err; |
| 837 |
} |
| 838 |
|
| 839 |
@@ -978,6 +982,12 @@ static const char *fbcon_startup(void) |
| 840 |
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); |
| 841 |
cols /= vc->vc_font.width; |
| 842 |
rows /= vc->vc_font.height; |
| 843 |
+ |
| 844 |
+ if (fbsplash_active(info, vc)) { |
| 845 |
+ cols = vc->vc_splash.twidth / vc->vc_font.width; |
| 846 |
+ rows = vc->vc_splash.theight / vc->vc_font.height; |
| 847 |
+ } |
| 848 |
+ |
| 849 |
vc_resize(vc, cols, rows); |
| 850 |
|
| 851 |
DPRINTK("mode: %s\n", info->fix.id); |
| 852 |
@@ -1060,7 +1070,7 @@ static void fbcon_init(struct vc_data *v |
| 853 |
cap = info->flags; |
| 854 |
|
| 855 |
if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW || |
| 856 |
- (info->fix.type == FB_TYPE_TEXT)) |
| 857 |
+ (info->fix.type == FB_TYPE_TEXT) || fbsplash_active(info, vc)) |
| 858 |
logo = 0; |
| 859 |
|
| 860 |
if (var_to_display(p, &info->var, info)) |
| 861 |
@@ -1200,6 +1210,11 @@ static void fbcon_clear(struct vc_data * |
| 862 |
if (!height || !width) |
| 863 |
return; |
| 864 |
|
| 865 |
+ if (fbsplash_active(info, vc)) { |
| 866 |
+ fbsplash_clear(vc, info, sy, sx, height, width); |
| 867 |
+ return; |
| 868 |
+ } |
| 869 |
+ |
| 870 |
/* Split blits that cross physical y_wrap boundary */ |
| 871 |
|
| 872 |
y_break = p->vrows - p->yscroll; |
| 873 |
@@ -1219,10 +1234,15 @@ static void fbcon_putcs(struct vc_data * |
| 874 |
struct display *p = &fb_display[vc->vc_num]; |
| 875 |
struct fbcon_ops *ops = info->fbcon_par; |
| 876 |
|
| 877 |
- if (!fbcon_is_inactive(vc, info)) |
| 878 |
- ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, |
| 879 |
- get_color(vc, info, scr_readw(s), 1), |
| 880 |
- get_color(vc, info, scr_readw(s), 0)); |
| 881 |
+ if (!fbcon_is_inactive(vc, info)) { |
| 882 |
+ |
| 883 |
+ if (fbsplash_active(info, vc)) |
| 884 |
+ fbsplash_putcs(vc, info, s, count, ypos, xpos); |
| 885 |
+ else |
| 886 |
+ ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, |
| 887 |
+ get_color(vc, info, scr_readw(s), 1), |
| 888 |
+ get_color(vc, info, scr_readw(s), 0)); |
| 889 |
+ } |
| 890 |
} |
| 891 |
|
| 892 |
static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) |
| 893 |
@@ -1238,8 +1258,13 @@ static void fbcon_clear_margins(struct v |
| 894 |
struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; |
| 895 |
struct fbcon_ops *ops = info->fbcon_par; |
| 896 |
|
| 897 |
- if (!fbcon_is_inactive(vc, info)) |
| 898 |
- ops->clear_margins(vc, info, bottom_only); |
| 899 |
+ if (!fbcon_is_inactive(vc, info)) { |
| 900 |
+ if (fbsplash_active(info, vc)) { |
| 901 |
+ fbsplash_clear_margins(vc, info, bottom_only); |
| 902 |
+ } else { |
| 903 |
+ ops->clear_margins(vc, info, bottom_only); |
| 904 |
+ } |
| 905 |
+ } |
| 906 |
} |
| 907 |
|
| 908 |
static void fbcon_cursor(struct vc_data *vc, int mode) |
| 909 |
@@ -1719,7 +1744,7 @@ static int fbcon_scroll(struct vc_data * |
| 910 |
count = vc->vc_rows; |
| 911 |
if (softback_top) |
| 912 |
fbcon_softback_note(vc, t, count); |
| 913 |
- if (logo_shown >= 0) |
| 914 |
+ if (logo_shown >= 0 || fbsplash_active(info, vc)) |
| 915 |
goto redraw_up; |
| 916 |
switch (p->scrollmode) { |
| 917 |
case SCROLL_MOVE: |
| 918 |
@@ -1807,6 +1832,8 @@ static int fbcon_scroll(struct vc_data * |
| 919 |
count = vc->vc_rows; |
| 920 |
if (logo_shown >= 0) |
| 921 |
goto redraw_down; |
| 922 |
+ if (fbsplash_active(info, vc)) |
| 923 |
+ goto redraw_down; |
| 924 |
switch (p->scrollmode) { |
| 925 |
case SCROLL_MOVE: |
| 926 |
ops->bmove(vc, info, t, 0, t + count, 0, |
| 927 |
@@ -1949,6 +1976,13 @@ static void fbcon_bmove_rec(struct vc_da |
| 928 |
} |
| 929 |
return; |
| 930 |
} |
| 931 |
+ |
| 932 |
+ if (fbsplash_active(info, vc) && sy == dy && height == 1) { |
| 933 |
+ /* must use slower redraw bmove to keep background pic intact */ |
| 934 |
+ fbsplash_bmove_redraw(vc, info, sy, sx, dx, width); |
| 935 |
+ return; |
| 936 |
+ } |
| 937 |
+ |
| 938 |
ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, |
| 939 |
height, width); |
| 940 |
} |
| 941 |
@@ -2018,8 +2052,9 @@ static int fbcon_resize(struct vc_data * |
| 942 |
var.yres = virt_h * virt_fh; |
| 943 |
x_diff = info->var.xres - var.xres; |
| 944 |
y_diff = info->var.yres - var.yres; |
| 945 |
- if (x_diff < 0 || x_diff > virt_fw || |
| 946 |
- y_diff < 0 || y_diff > virt_fh) { |
| 947 |
+ |
| 948 |
+ if ((x_diff < 0 || x_diff > virt_fw || |
| 949 |
+ y_diff < 0 || y_diff > virt_fh) && !vc->vc_splash.state) { |
| 950 |
struct fb_videomode *mode; |
| 951 |
|
| 952 |
DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); |
| 953 |
@@ -2055,7 +2090,26 @@ static int fbcon_switch(struct vc_data * |
| 954 |
|
| 955 |
info = registered_fb[con2fb_map[vc->vc_num]]; |
| 956 |
ops = info->fbcon_par; |
| 957 |
- |
| 958 |
+ prev_console = ops->currcon; |
| 959 |
+ if (prev_console != -1) |
| 960 |
+ old_info = registered_fb[con2fb_map[prev_console]]; |
| 961 |
+ |
| 962 |
+ if (fbsplash_active_vc(vc)) { |
| 963 |
+ struct vc_data *vc_curr = vc_cons[prev_console].d; |
| 964 |
+ if (!vc_curr->vc_splash.theme || strcmp(vc->vc_splash.theme, vc_curr->vc_splash.theme)) { |
| 965 |
+ if (fbsplash_call_helper("getpic", vc->vc_num)) |
| 966 |
+ fbsplash_disable(vc, 0); |
| 967 |
+ } |
| 968 |
+ } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { |
| 969 |
+ struct vc_data *vc_curr = vc_cons[prev_console].d; |
| 970 |
+ if (vc_curr && fbsplash_active_vc(vc_curr)) { |
| 971 |
+ /* Clear the screen to avoid displaying funky colors during |
| 972 |
+ * palette updates. */ |
| 973 |
+ memset((u8*)info->screen_base + info->fix.line_length * info->var.yoffset, |
| 974 |
+ 0, info->var.yres * info->fix.line_length); |
| 975 |
+ } |
| 976 |
+ } |
| 977 |
+ |
| 978 |
if (softback_top) { |
| 979 |
if (softback_lines) |
| 980 |
fbcon_set_origin(vc); |
| 981 |
@@ -2073,9 +2127,6 @@ static int fbcon_switch(struct vc_data * |
| 982 |
logo_shown = FBCON_LOGO_CANSHOW; |
| 983 |
} |
| 984 |
|
| 985 |
- prev_console = ops->currcon; |
| 986 |
- if (prev_console != -1) |
| 987 |
- old_info = registered_fb[con2fb_map[prev_console]]; |
| 988 |
/* |
| 989 |
* FIXME: If we have multiple fbdev's loaded, we need to |
| 990 |
* update all info->currcon. Perhaps, we can place this |
| 991 |
@@ -2113,6 +2164,11 @@ static int fbcon_switch(struct vc_data * |
| 992 |
fbcon_add_cursor_timer(info); |
| 993 |
} |
| 994 |
|
| 995 |
+ if (fbsplash_active_nores(info, vc) && !fbsplash_active(info, vc)) { |
| 996 |
+ if (fbsplash_call_helper("modechange", vc->vc_num)) |
| 997 |
+ fbsplash_disable(vc, 0); |
| 998 |
+ } |
| 999 |
+ |
| 1000 |
set_blitting_type(vc, info, p); |
| 1001 |
ops->cursor_reset = 1; |
| 1002 |
|
| 1003 |
@@ -2200,8 +2256,12 @@ static int fbcon_blank(struct vc_data *v |
| 1004 |
fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW); |
| 1005 |
ops->cursor_flash = (!blank); |
| 1006 |
|
| 1007 |
- if (fb_blank(info, blank)) |
| 1008 |
- fbcon_generic_blank(vc, info, blank); |
| 1009 |
+ if (fb_blank(info, blank)) { |
| 1010 |
+ if (fbsplash_active(info, vc)) |
| 1011 |
+ fbsplash_blank(vc, info, blank); |
| 1012 |
+ else |
| 1013 |
+ fbcon_generic_blank(vc, info, blank); |
| 1014 |
+ } |
| 1015 |
} |
| 1016 |
|
| 1017 |
if (!blank) |
| 1018 |
@@ -2359,13 +2419,22 @@ static int fbcon_do_set_font(struct vc_d |
| 1019 |
} |
| 1020 |
|
| 1021 |
if (resize) { |
| 1022 |
+ /* reset wrap/pan */ |
| 1023 |
int cols, rows; |
| 1024 |
|
| 1025 |
cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); |
| 1026 |
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); |
| 1027 |
+ |
| 1028 |
+ info->var.xoffset = info->var.yoffset = p->yscroll = 0; |
| 1029 |
+ if (fbsplash_active(info, vc)) { |
| 1030 |
+ cols = vc->vc_splash.twidth; |
| 1031 |
+ rows = vc->vc_splash.theight; |
| 1032 |
+ } |
| 1033 |
cols /= w; |
| 1034 |
rows /= h; |
| 1035 |
+ |
| 1036 |
vc_resize(vc, cols, rows); |
| 1037 |
+ |
| 1038 |
if (CON_IS_VISIBLE(vc) && softback_buf) |
| 1039 |
fbcon_update_softback(vc); |
| 1040 |
} else if (CON_IS_VISIBLE(vc) |
| 1041 |
@@ -2483,7 +2552,7 @@ static int fbcon_set_palette(struct vc_d |
| 1042 |
int i, j, k, depth; |
| 1043 |
u8 val; |
| 1044 |
|
| 1045 |
- if (fbcon_is_inactive(vc, info)) |
| 1046 |
+ if (fbcon_is_inactive(vc, info) || vc->vc_num != fg_console) |
| 1047 |
return -EINVAL; |
| 1048 |
|
| 1049 |
if (!CON_IS_VISIBLE(vc)) |
| 1050 |
@@ -2509,7 +2578,49 @@ static int fbcon_set_palette(struct vc_d |
| 1051 |
} else |
| 1052 |
fb_copy_cmap(fb_default_cmap(1 << depth), &palette_cmap); |
| 1053 |
|
| 1054 |
- return fb_set_cmap(&palette_cmap, info); |
| 1055 |
+ if (fbsplash_active(info, vc_cons[fg_console].d) && |
| 1056 |
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) { |
| 1057 |
+ |
| 1058 |
+ u16 *red, *green, *blue; |
| 1059 |
+ int minlen = min(min(info->var.red.length, info->var.green.length), |
| 1060 |
+ info->var.blue.length); |
| 1061 |
+ int h; |
| 1062 |
+ |
| 1063 |
+ struct fb_cmap cmap = { |
| 1064 |
+ .start = 0, |
| 1065 |
+ .len = (1 << minlen), |
| 1066 |
+ .red = NULL, |
| 1067 |
+ .green = NULL, |
| 1068 |
+ .blue = NULL, |
| 1069 |
+ .transp = NULL |
| 1070 |
+ }; |
| 1071 |
+ |
| 1072 |
+ red = kmalloc(256 * sizeof(u16) * 3, GFP_KERNEL); |
| 1073 |
+ |
| 1074 |
+ if (!red) |
| 1075 |
+ goto out; |
| 1076 |
+ |
| 1077 |
+ green = red + 256; |
| 1078 |
+ blue = green + 256; |
| 1079 |
+ cmap.red = red; |
| 1080 |
+ cmap.green = green; |
| 1081 |
+ cmap.blue = blue; |
| 1082 |
+ |
| 1083 |
+ for (i = 0; i < cmap.len; i++) { |
| 1084 |
+ red[i] = green[i] = blue[i] = (0xffff * i)/(cmap.len-1); |
| 1085 |
+ } |
| 1086 |
+ |
| 1087 |
+ h = fb_set_cmap(&cmap, info); |
| 1088 |
+ fbsplash_fix_pseudo_pal(info, vc_cons[fg_console].d); |
| 1089 |
+ kfree(red); |
| 1090 |
+ |
| 1091 |
+ return h; |
| 1092 |
+ |
| 1093 |
+ } else if (fbsplash_active(info, vc_cons[fg_console].d) && |
| 1094 |
+ info->var.bits_per_pixel == 8 && info->splash.cmap.red != NULL) |
| 1095 |
+ fb_set_cmap(&info->splash.cmap, info); |
| 1096 |
+ |
| 1097 |
+out: return fb_set_cmap(&palette_cmap, info); |
| 1098 |
} |
| 1099 |
|
| 1100 |
static u16 *fbcon_screen_pos(struct vc_data *vc, int offset) |
| 1101 |
@@ -2735,7 +2846,14 @@ static void fbcon_modechanged(struct fb_ |
| 1102 |
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); |
| 1103 |
cols /= vc->vc_font.width; |
| 1104 |
rows /= vc->vc_font.height; |
| 1105 |
- vc_resize(vc, cols, rows); |
| 1106 |
+ |
| 1107 |
+ if (!fbsplash_active_nores(info, vc)) { |
| 1108 |
+ vc_resize(vc, cols, rows); |
| 1109 |
+ } else { |
| 1110 |
+ if (fbsplash_call_helper("modechange", vc->vc_num)) |
| 1111 |
+ fbsplash_disable(vc, 0); |
| 1112 |
+ } |
| 1113 |
+ |
| 1114 |
updatescrollmode(p, info, vc); |
| 1115 |
scrollback_max = 0; |
| 1116 |
scrollback_current = 0; |
| 1117 |
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c |
| 1118 |
index c32a2a5..3a227fa 100644 |
| 1119 |
--- a/drivers/video/fbcmap.c |
| 1120 |
+++ b/drivers/video/fbcmap.c |
| 1121 |
@@ -16,6 +16,7 @@ |
| 1122 |
#include <linux/tty.h> |
| 1123 |
#include <linux/fb.h> |
| 1124 |
#include <linux/slab.h> |
| 1125 |
+#include "fbsplash.h" |
| 1126 |
|
| 1127 |
#include <asm/uaccess.h> |
| 1128 |
|
| 1129 |
@@ -235,14 +236,17 @@ int fb_set_cmap(struct fb_cmap *cmap, st |
| 1130 |
if (transp) |
| 1131 |
htransp = *transp++; |
| 1132 |
if (info->fbops->fb_setcolreg(start++, |
| 1133 |
- hred, hgreen, hblue, |
| 1134 |
+ hred, hgreen, hblue, |
| 1135 |
htransp, info)) |
| 1136 |
break; |
| 1137 |
} |
| 1138 |
} |
| 1139 |
- if (rc == 0) |
| 1140 |
+ if (rc == 0) { |
| 1141 |
fb_copy_cmap(cmap, &info->cmap); |
| 1142 |
- |
| 1143 |
+ if (fbsplash_active(info, vc_cons[fg_console].d) && |
| 1144 |
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) |
| 1145 |
+ fbsplash_fix_pseudo_pal(info, vc_cons[fg_console].d); |
| 1146 |
+ } |
| 1147 |
return rc; |
| 1148 |
} |
| 1149 |
|
| 1150 |
@@ -250,7 +254,7 @@ int fb_set_user_cmap(struct fb_cmap_user |
| 1151 |
{ |
| 1152 |
int rc, size = cmap->len * sizeof(u16); |
| 1153 |
struct fb_cmap umap; |
| 1154 |
- |
| 1155 |
+ |
| 1156 |
if (cmap->start < 0 || (!info->fbops->fb_setcolreg && |
| 1157 |
!info->fbops->fb_setcmap)) |
| 1158 |
return -EINVAL; |
| 1159 |
diff --git a/drivers/video/fbsplash.c b/drivers/video/fbsplash.c |
| 1160 |
new file mode 100644 |
| 1161 |
index 0000000..a12d5b8 |
| 1162 |
--- /dev/null |
| 1163 |
+++ b/drivers/video/fbsplash.c |
| 1164 |
@@ -0,0 +1,406 @@ |
| 1165 |
+/* |
| 1166 |
+ * linux/drivers/video/fbsplash.c -- Framebuffer splash routines |
| 1167 |
+ * |
| 1168 |
+ * Copyright (C) 2004 Michal Januszewski <spock@gentoo.org> |
| 1169 |
+ * |
| 1170 |
+ * Code based upon "Bootsplash" (C) 2001-2003 |
| 1171 |
+ * Volker Poplawski <volker@poplawski.de>, |
| 1172 |
+ * Stefan Reinauer <stepan@suse.de>, |
| 1173 |
+ * Steffen Winterfeldt <snwint@suse.de>, |
| 1174 |
+ * Michael Schroeder <mls@suse.de>, |
| 1175 |
+ * Ken Wimer <wimer@suse.de>. |
| 1176 |
+ * |
| 1177 |
+ * Splash render routines are located in /linux/drivers/video/cfbsplash.c |
| 1178 |
+ * |
| 1179 |
+ * This file is subject to the terms and conditions of the GNU General Public |
| 1180 |
+ * License. See the file COPYING in the main directory of this archive for |
| 1181 |
+ * more details. |
| 1182 |
+ * |
| 1183 |
+ */ |
| 1184 |
+#include <linux/config.h> |
| 1185 |
+#include <linux/module.h> |
| 1186 |
+#include <linux/kernel.h> |
| 1187 |
+#include <linux/string.h> |
| 1188 |
+#include <linux/types.h> |
| 1189 |
+#include <linux/fb.h> |
| 1190 |
+#include <linux/vt_kern.h> |
| 1191 |
+#include <linux/vmalloc.h> |
| 1192 |
+#include <linux/unistd.h> |
| 1193 |
+#include <linux/syscalls.h> |
| 1194 |
+#include <linux/init.h> |
| 1195 |
+#include <linux/proc_fs.h> |
| 1196 |
+#include <linux/workqueue.h> |
| 1197 |
+#include <linux/kmod.h> |
| 1198 |
+#include <linux/miscdevice.h> |
| 1199 |
+#include <linux/device.h> |
| 1200 |
+#include <linux/fs.h> |
| 1201 |
+ |
| 1202 |
+#include <asm/uaccess.h> |
| 1203 |
+#include <asm/irq.h> |
| 1204 |
+#include <asm/system.h> |
| 1205 |
+ |
| 1206 |
+#include "console/fbcon.h" |
| 1207 |
+#include "fbsplash.h" |
| 1208 |
+ |
| 1209 |
+#define SPLASH_VERSION "0.9.2" |
| 1210 |
+ |
| 1211 |
+extern signed char con2fb_map[]; |
| 1212 |
+static int fbsplash_enable(struct vc_data *vc); |
| 1213 |
+char fbsplash_path[KMOD_PATH_LEN] = "/sbin/splash_helper"; |
| 1214 |
+ |
| 1215 |
+int fbsplash_call_helper(char* cmd, unsigned short vc) |
| 1216 |
+{ |
| 1217 |
+ char *envp[] = { |
| 1218 |
+ "HOME=/", |
| 1219 |
+ "PATH=/sbin:/bin", |
| 1220 |
+ NULL |
| 1221 |
+ }; |
| 1222 |
+ |
| 1223 |
+ char tfb[5]; |
| 1224 |
+ char tcons[5]; |
| 1225 |
+ unsigned char fb = (int) con2fb_map[vc]; |
| 1226 |
+ |
| 1227 |
+ char *argv[] = { |
| 1228 |
+ fbsplash_path, |
| 1229 |
+ "2", |
| 1230 |
+ cmd, |
| 1231 |
+ tcons, |
| 1232 |
+ tfb, |
| 1233 |
+ vc_cons[vc].d->vc_splash.theme, |
| 1234 |
+ NULL |
| 1235 |
+ }; |
| 1236 |
+ |
| 1237 |
+ snprintf(tfb,5,"%d",fb); |
| 1238 |
+ snprintf(tcons,5,"%d",vc); |
| 1239 |
+ |
| 1240 |
+ return call_usermodehelper(fbsplash_path, argv, envp, 1); |
| 1241 |
+} |
| 1242 |
+ |
| 1243 |
+/* Disables fbsplash on a virtual console; called with console sem held. */ |
| 1244 |
+int fbsplash_disable(struct vc_data *vc, unsigned char redraw) |
| 1245 |
+{ |
| 1246 |
+ struct fb_info* info; |
| 1247 |
+ |
| 1248 |
+ if (!vc->vc_splash.state) |
| 1249 |
+ return -EINVAL; |
| 1250 |
+ |
| 1251 |
+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; |
| 1252 |
+ |
| 1253 |
+ if (info == NULL) |
| 1254 |
+ return -EINVAL; |
| 1255 |
+ |
| 1256 |
+ vc->vc_splash.state = 0; |
| 1257 |
+ vc_resize(vc, info->var.xres / vc->vc_font.width, |
| 1258 |
+ info->var.yres / vc->vc_font.height); |
| 1259 |
+ |
| 1260 |
+ if (fg_console == vc->vc_num && redraw) { |
| 1261 |
+ redraw_screen(vc, 0); |
| 1262 |
+ update_region(vc, vc->vc_origin + |
| 1263 |
+ vc->vc_size_row * vc->vc_top, |
| 1264 |
+ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); |
| 1265 |
+ } |
| 1266 |
+ |
| 1267 |
+ printk(KERN_INFO "fbsplash: switched splash state to 'off' on console %d\n", |
| 1268 |
+ vc->vc_num); |
| 1269 |
+ |
| 1270 |
+ return 0; |
| 1271 |
+} |
| 1272 |
+ |
| 1273 |
+/* Enables fbsplash on a virtual console; called with console sem held. */ |
| 1274 |
+static int fbsplash_enable(struct vc_data *vc) |
| 1275 |
+{ |
| 1276 |
+ struct fb_info* info; |
| 1277 |
+ |
| 1278 |
+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; |
| 1279 |
+ |
| 1280 |
+ if (vc->vc_splash.twidth == 0 || vc->vc_splash.theight == 0 || |
| 1281 |
+ info == NULL || vc->vc_splash.state || (!info->splash.data && |
| 1282 |
+ vc->vc_num == fg_console)) |
| 1283 |
+ return -EINVAL; |
| 1284 |
+ |
| 1285 |
+ vc->vc_splash.state = 1; |
| 1286 |
+ vc_resize(vc, vc->vc_splash.twidth / vc->vc_font.width, |
| 1287 |
+ vc->vc_splash.theight / vc->vc_font.height); |
| 1288 |
+ |
| 1289 |
+ if (fg_console == vc->vc_num) { |
| 1290 |
+ redraw_screen(vc, 0); |
| 1291 |
+ update_region(vc, vc->vc_origin + |
| 1292 |
+ vc->vc_size_row * vc->vc_top, |
| 1293 |
+ vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2); |
| 1294 |
+ fbsplash_clear_margins(vc, info, 0); |
| 1295 |
+ } |
| 1296 |
+ |
| 1297 |
+ printk(KERN_INFO "fbsplash: switched splash state to 'on' on console %d\n", |
| 1298 |
+ vc->vc_num); |
| 1299 |
+ |
| 1300 |
+ return 0; |
| 1301 |
+} |
| 1302 |
+ |
| 1303 |
+static inline int fbsplash_ioctl_dosetstate(struct vc_data *vc, unsigned int __user* state, unsigned char origin) |
| 1304 |
+{ |
| 1305 |
+ int tmp, ret; |
| 1306 |
+ |
| 1307 |
+ if (get_user(tmp, state)) |
| 1308 |
+ return -EFAULT; |
| 1309 |
+ |
| 1310 |
+ if (origin == FB_SPLASH_IO_ORIG_USER) |
| 1311 |
+ acquire_console_sem(); |
| 1312 |
+ if (!tmp) |
| 1313 |
+ ret = fbsplash_disable(vc, 1); |
| 1314 |
+ else |
| 1315 |
+ ret = fbsplash_enable(vc); |
| 1316 |
+ if (origin == FB_SPLASH_IO_ORIG_USER) |
| 1317 |
+ release_console_sem(); |
| 1318 |
+ |
| 1319 |
+ return ret; |
| 1320 |
+} |
| 1321 |
+ |
| 1322 |
+static inline int fbsplash_ioctl_dogetstate(struct vc_data *vc, unsigned int __user *state) |
| 1323 |
+{ |
| 1324 |
+ return put_user(vc->vc_splash.state, (unsigned int __user*) state); |
| 1325 |
+} |
| 1326 |
+ |
| 1327 |
+static int fbsplash_ioctl_dosetcfg(struct vc_data *vc, struct vc_splash __user *arg, unsigned char origin) |
| 1328 |
+{ |
| 1329 |
+ struct vc_splash cfg; |
| 1330 |
+ struct fb_info *info; |
| 1331 |
+ int len; |
| 1332 |
+ char *tmp; |
| 1333 |
+ |
| 1334 |
+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; |
| 1335 |
+ |
| 1336 |
+ if (copy_from_user(&cfg, arg, sizeof(struct vc_splash))) |
| 1337 |
+ return -EFAULT; |
| 1338 |
+ if (info == NULL || !cfg.twidth || !cfg.theight || |
| 1339 |
+ cfg.tx + cfg.twidth > info->var.xres || |
| 1340 |
+ cfg.ty + cfg.theight > info->var.yres) |
| 1341 |
+ return -EINVAL; |
| 1342 |
+ |
| 1343 |
+ len = strlen_user(cfg.theme); |
| 1344 |
+ if (!len || len > FB_SPLASH_THEME_LEN) |
| 1345 |
+ return -EINVAL; |
| 1346 |
+ tmp = kmalloc(len, GFP_KERNEL); |
| 1347 |
+ if (!tmp) |
| 1348 |
+ return -ENOMEM; |
| 1349 |
+ if (copy_from_user(tmp, (void __user *)cfg.theme, len)) |
| 1350 |
+ return -EFAULT; |
| 1351 |
+ cfg.theme = tmp; |
| 1352 |
+ cfg.state = 0; |
| 1353 |
+ |
| 1354 |
+ /* If this ioctl is a response to a request from kernel, the console sem |
| 1355 |
+ * is already held; we also don't need to disable splash because either the |
| 1356 |
+ * new config and background picture will be successfully loaded, and the |
| 1357 |
+ * splash will stay on, or in case of a failure it'll be turned off in fbcon. */ |
| 1358 |
+ if (origin == FB_SPLASH_IO_ORIG_USER) { |
| 1359 |
+ acquire_console_sem(); |
| 1360 |
+ if (vc->vc_splash.state) |
| 1361 |
+ fbsplash_disable(vc, 1); |
| 1362 |
+ } |
| 1363 |
+ |
| 1364 |
+ if (vc->vc_splash.theme) |
| 1365 |
+ kfree(vc->vc_splash.theme); |
| 1366 |
+ |
| 1367 |
+ vc->vc_splash = cfg; |
| 1368 |
+ |
| 1369 |
+ if (origin == FB_SPLASH_IO_ORIG_USER) |
| 1370 |
+ release_console_sem(); |
| 1371 |
+ |
| 1372 |
+ printk(KERN_INFO "fbsplash: console %d using theme '%s'\n", |
| 1373 |
+ vc->vc_num, vc->vc_splash.theme); |
| 1374 |
+ return 0; |
| 1375 |
+} |
| 1376 |
+ |
| 1377 |
+static int fbsplash_ioctl_dogetcfg(struct vc_data *vc, struct vc_splash __user *arg) |
| 1378 |
+{ |
| 1379 |
+ struct vc_splash splash; |
| 1380 |
+ char __user *tmp; |
| 1381 |
+ |
| 1382 |
+ if (get_user(tmp, &arg->theme)) |
| 1383 |
+ return -EFAULT; |
| 1384 |
+ |
| 1385 |
+ splash = vc->vc_splash; |
| 1386 |
+ splash.theme = tmp; |
| 1387 |
+ |
| 1388 |
+ if (vc->vc_splash.theme) { |
| 1389 |
+ if (copy_to_user(tmp, vc->vc_splash.theme, strlen(vc->vc_splash.theme) + 1)) |
| 1390 |
+ return -EFAULT; |
| 1391 |
+ } else |
| 1392 |
+ if (put_user(0, tmp)) |
| 1393 |
+ return -EFAULT; |
| 1394 |
+ |
| 1395 |
+ if (copy_to_user(arg, &splash, sizeof(struct vc_splash))) |
| 1396 |
+ return -EFAULT; |
| 1397 |
+ |
| 1398 |
+ return 0; |
| 1399 |
+} |
| 1400 |
+ |
| 1401 |
+static int fbsplash_ioctl_dosetpic(struct vc_data *vc, struct fb_image __user *arg, unsigned char origin) |
| 1402 |
+{ |
| 1403 |
+ struct fb_image img; |
| 1404 |
+ struct fb_info *info; |
| 1405 |
+ int len; |
| 1406 |
+ u8 *tmp; |
| 1407 |
+ |
| 1408 |
+ if (vc->vc_num != fg_console) |
| 1409 |
+ return -EINVAL; |
| 1410 |
+ |
| 1411 |
+ info = registered_fb[(int) con2fb_map[vc->vc_num]]; |
| 1412 |
+ |
| 1413 |
+ if (info == NULL) |
| 1414 |
+ return -EINVAL; |
| 1415 |
+ |
| 1416 |
+ if (copy_from_user(&img, arg, sizeof(struct fb_image))) |
| 1417 |
+ return -EFAULT; |
| 1418 |
+ |
| 1419 |
+ if (img.width != info->var.xres || img.height != info->var.yres) { |
| 1420 |
+ printk(KERN_ERR "fbsplash: picture dimensions mismatch\n"); |
| 1421 |
+ return -EINVAL; |
| 1422 |
+ } |
| 1423 |
+ |
| 1424 |
+ if (img.depth != info->var.bits_per_pixel) { |
| 1425 |
+ printk(KERN_ERR "fbsplash: picture depth mismatch\n"); |
| 1426 |
+ return -EINVAL; |
| 1427 |
+ } |
| 1428 |
+ |
| 1429 |
+ if (img.depth == 8) { |
| 1430 |
+ if (!img.cmap.len || !img.cmap.red || !img.cmap.green || |
| 1431 |
+ !img.cmap.blue) |
| 1432 |
+ return -EINVAL; |
| 1433 |
+ |
| 1434 |
+ tmp = vmalloc(img.cmap.len * 3 * 2); |
| 1435 |
+ if (!tmp) |
| 1436 |
+ return -ENOMEM; |
| 1437 |
+ |
| 1438 |
+ if (copy_from_user(tmp, (void __user*)img.cmap.red, img.cmap.len * 2) || |
| 1439 |
+ copy_from_user(tmp + (img.cmap.len << 1), |
| 1440 |
+ (void __user*)img.cmap.green, (img.cmap.len << 1)) || |
| 1441 |
+ copy_from_user(tmp + (img.cmap.len << 2), |
| 1442 |
+ (void __user*)img.cmap.blue, (img.cmap.len << 1))) { |
| 1443 |
+ vfree(tmp); |
| 1444 |
+ return -EFAULT; |
| 1445 |
+ } |
| 1446 |
+ |
| 1447 |
+ img.cmap.transp = NULL; |
| 1448 |
+ img.cmap.red = (u16*)tmp; |
| 1449 |
+ img.cmap.green = img.cmap.red + img.cmap.len; |
| 1450 |
+ img.cmap.blue = img.cmap.green + img.cmap.len; |
| 1451 |
+ } else { |
| 1452 |
+ img.cmap.red = NULL; |
| 1453 |
+ } |
| 1454 |
+ |
| 1455 |
+ len = ((img.depth + 7) >> 3) * img.width * img.height; |
| 1456 |
+ tmp = vmalloc(len); |
| 1457 |
+ |
| 1458 |
+ if (!tmp) |
| 1459 |
+ goto out; |
| 1460 |
+ |
| 1461 |
+ if (copy_from_user(tmp, (void __user*)img.data, len)) |
| 1462 |
+ goto out; |
| 1463 |
+ |
| 1464 |
+ img.data = tmp; |
| 1465 |
+ |
| 1466 |
+ /* If this ioctl is a response to a request from kernel, the console sem |
| 1467 |
+ * is already held. */ |
| 1468 |
+ if (origin == FB_SPLASH_IO_ORIG_USER) |
| 1469 |
+ acquire_console_sem(); |
| 1470 |
+ |
| 1471 |
+ if (info->splash.data) |
| 1472 |
+ vfree((u8*)info->splash.data); |
| 1473 |
+ if (info->splash.cmap.red) |
| 1474 |
+ vfree(info->splash.cmap.red); |
| 1475 |
+ |
| 1476 |
+ info->splash = img; |
| 1477 |
+ |
| 1478 |
+ if (origin == FB_SPLASH_IO_ORIG_USER) |
| 1479 |
+ release_console_sem(); |
| 1480 |
+ |
| 1481 |
+ return 0; |
| 1482 |
+ |
| 1483 |
+out: if (img.cmap.red) |
| 1484 |
+ vfree(img.cmap.red); |
| 1485 |
+ if (tmp) |
| 1486 |
+ vfree(tmp); |
| 1487 |
+ return -ENOMEM; |
| 1488 |
+} |
| 1489 |
+ |
| 1490 |
+static int splash_ioctl(struct inode * inode, struct file *filp, u_int cmd, |
| 1491 |
+ u_long arg) |
| 1492 |
+{ |
| 1493 |
+ struct fb_splash_iowrapper __user *wrapper = (void __user*) arg; |
| 1494 |
+ struct vc_data *vc = NULL; |
| 1495 |
+ unsigned short vc_num = 0; |
| 1496 |
+ unsigned char origin = 0; |
| 1497 |
+ void __user *data = NULL; |
| 1498 |
+ |
| 1499 |
+ if (!access_ok(VERIFY_READ, wrapper, |
| 1500 |
+ sizeof(struct fb_splash_iowrapper))) |
| 1501 |
+ return -EFAULT; |
| 1502 |
+ |
| 1503 |
+ __get_user(vc_num, &wrapper->vc); |
| 1504 |
+ __get_user(origin, &wrapper->origin); |
| 1505 |
+ __get_user(data, &wrapper->data); |
| 1506 |
+ |
| 1507 |
+ if (!vc_cons_allocated(vc_num)) |
| 1508 |
+ return -EINVAL; |
| 1509 |
+ |
| 1510 |
+ vc = vc_cons[vc_num].d; |
| 1511 |
+ |
| 1512 |
+ switch (cmd) { |
| 1513 |
+ case FBIOSPLASH_SETPIC: |
| 1514 |
+ return fbsplash_ioctl_dosetpic(vc, (struct fb_image __user*)data, origin); |
| 1515 |
+ case FBIOSPLASH_SETCFG: |
| 1516 |
+ return fbsplash_ioctl_dosetcfg(vc, (struct vc_splash*)data, origin); |
| 1517 |
+ case FBIOSPLASH_GETCFG: |
| 1518 |
+ return fbsplash_ioctl_dogetcfg(vc, (struct vc_splash*)data); |
| 1519 |
+ case FBIOSPLASH_SETSTATE: |
| 1520 |
+ return fbsplash_ioctl_dosetstate(vc, (unsigned int *)data, origin); |
| 1521 |
+ case FBIOSPLASH_GETSTATE: |
| 1522 |
+ return fbsplash_ioctl_dogetstate(vc, (unsigned int *)data); |
| 1523 |
+ default: |
| 1524 |
+ return -ENOIOCTLCMD; |
| 1525 |
+ } |
| 1526 |
+} |
| 1527 |
+ |
| 1528 |
+static struct file_operations splash_ops = { |
| 1529 |
+ .owner = THIS_MODULE, |
| 1530 |
+ .ioctl = splash_ioctl |
| 1531 |
+}; |
| 1532 |
+ |
| 1533 |
+static struct miscdevice splash_dev = { |
| 1534 |
+ .minor = MISC_DYNAMIC_MINOR, |
| 1535 |
+ .name = "fbsplash", |
| 1536 |
+ .fops = &splash_ops |
| 1537 |
+}; |
| 1538 |
+ |
| 1539 |
+int fbsplash_init(void) |
| 1540 |
+{ |
| 1541 |
+ struct fb_info *info; |
| 1542 |
+ struct vc_data *vc; |
| 1543 |
+ int i; |
| 1544 |
+ |
| 1545 |
+ vc = vc_cons[0].d; |
| 1546 |
+ info = registered_fb[0]; |
| 1547 |
+ |
| 1548 |
+ for (i = 0; i < num_registered_fb; i++) { |
| 1549 |
+ registered_fb[i]->splash.data = NULL; |
| 1550 |
+ registered_fb[i]->splash.cmap.red = NULL; |
| 1551 |
+ } |
| 1552 |
+ |
| 1553 |
+ for (i = 0; i < MAX_NR_CONSOLES && vc_cons[i].d; i++) { |
| 1554 |
+ vc_cons[i].d->vc_splash.state = vc_cons[i].d->vc_splash.twidth = |
| 1555 |
+ vc_cons[i].d->vc_splash.theight = 0; |
| 1556 |
+ vc_cons[i].d->vc_splash.theme = NULL; |
| 1557 |
+ } |
| 1558 |
+ |
| 1559 |
+ i = misc_register(&splash_dev); |
| 1560 |
+ if (i) { |
| 1561 |
+ printk(KERN_ERR "fbsplash: failed to register device\n"); |
| 1562 |
+ return i; |
| 1563 |
+ } |
| 1564 |
+ |
| 1565 |
+ fbsplash_call_helper("init", 0); |
| 1566 |
+ |
| 1567 |
+ return 0; |
| 1568 |
+} |
| 1569 |
+ |
| 1570 |
+EXPORT_SYMBOL(fbsplash_path); |
| 1571 |
diff --git a/drivers/video/fbsplash.h b/drivers/video/fbsplash.h |
| 1572 |
new file mode 100644 |
| 1573 |
index 0000000..211fa23 |
| 1574 |
--- /dev/null |
| 1575 |
+++ b/drivers/video/fbsplash.h |
| 1576 |
@@ -0,0 +1,76 @@ |
| 1577 |
+/* |
| 1578 |
+ * linux/drivers/video/fbsplash.h -- Framebuffer splash headers |
| 1579 |
+ * |
| 1580 |
+ * Copyright (C) 2004 Michal Januszewski <spock@gentoo.org> |
| 1581 |
+ * |
| 1582 |
+ */ |
| 1583 |
+ |
| 1584 |
+#ifndef __FB_SPLASH_H |
| 1585 |
+#define __FB_SPLASH_H |
| 1586 |
+ |
| 1587 |
+#ifndef _LINUX_FB_H |
| 1588 |
+#include <linux/fb.h> |
| 1589 |
+#endif |
| 1590 |
+ |
| 1591 |
+/* This is needed for vc_cons in fbcmap.c */ |
| 1592 |
+#include <linux/vt_kern.h> |
| 1593 |
+ |
| 1594 |
+struct fb_cursor; |
| 1595 |
+struct fb_info; |
| 1596 |
+struct vc_data; |
| 1597 |
+ |
| 1598 |
+#ifdef CONFIG_FB_SPLASH |
| 1599 |
+/* fbsplash.c */ |
| 1600 |
+int fbsplash_init(void); |
| 1601 |
+int fbsplash_call_helper(char* cmd, unsigned short cons); |
| 1602 |
+int fbsplash_disable(struct vc_data *vc, unsigned char redraw); |
| 1603 |
+ |
| 1604 |
+/* cfbsplash.c */ |
| 1605 |
+void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx); |
| 1606 |
+void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor); |
| 1607 |
+void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width); |
| 1608 |
+void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only); |
| 1609 |
+void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank); |
| 1610 |
+void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width); |
| 1611 |
+void fbsplash_copy(u8 *dst, u8 *src, int height, int width, int linebytes, int srclinesbytes, int bpp); |
| 1612 |
+void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc); |
| 1613 |
+ |
| 1614 |
+/* vt.c */ |
| 1615 |
+void acquire_console_sem(void); |
| 1616 |
+void release_console_sem(void); |
| 1617 |
+void do_unblank_screen(int entering_gfx); |
| 1618 |
+ |
| 1619 |
+/* struct vc_data *y */ |
| 1620 |
+#define fbsplash_active_vc(y) (y->vc_splash.state && y->vc_splash.theme) |
| 1621 |
+ |
| 1622 |
+/* struct fb_info *x, struct vc_data *y */ |
| 1623 |
+#define fbsplash_active_nores(x,y) (x->splash.data && fbsplash_active_vc(y)) |
| 1624 |
+ |
| 1625 |
+/* struct fb_info *x, struct vc_data *y */ |
| 1626 |
+#define fbsplash_active(x,y) (fbsplash_active_nores(x,y) && \ |
| 1627 |
+ x->splash.width == x->var.xres && \ |
| 1628 |
+ x->splash.height == x->var.yres && \ |
| 1629 |
+ x->splash.depth == x->var.bits_per_pixel) |
| 1630 |
+ |
| 1631 |
+ |
| 1632 |
+#else /* CONFIG_FB_SPLASH */ |
| 1633 |
+ |
| 1634 |
+static inline void fbsplash_putcs(struct vc_data *vc, struct fb_info *info, const unsigned short *s, int count, int yy, int xx) {} |
| 1635 |
+static inline void fbsplash_putc(struct vc_data *vc, struct fb_info *info, int c, int ypos, int xpos) {} |
| 1636 |
+static inline void fbsplash_cursor(struct fb_info *info, struct fb_cursor *cursor) {} |
| 1637 |
+static inline void fbsplash_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width) {} |
| 1638 |
+static inline void fbsplash_clear_margins(struct vc_data *vc, struct fb_info *info, int bottom_only) {} |
| 1639 |
+static inline void fbsplash_blank(struct vc_data *vc, struct fb_info *info, int blank) {} |
| 1640 |
+static inline void fbsplash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width) {} |
| 1641 |
+static inline void fbsplash_fix_pseudo_pal(struct fb_info *info, struct vc_data *vc) {} |
| 1642 |
+static inline int fbsplash_call_helper(char* cmd, unsigned short cons) { return 0; } |
| 1643 |
+static inline int fbsplash_init(void) { return 0; } |
| 1644 |
+static inline int fbsplash_disable(struct vc_data *vc, unsigned char redraw) { return 0; } |
| 1645 |
+ |
| 1646 |
+#define fbsplash_active_vc(y) (0) |
| 1647 |
+#define fbsplash_active_nores(x,y) (0) |
| 1648 |
+#define fbsplash_active(x,y) (0) |
| 1649 |
+ |
| 1650 |
+#endif /* CONFIG_FB_SPLASH */ |
| 1651 |
+ |
| 1652 |
+#endif /* __FB_SPLASH_H */ |
| 1653 |
diff --git a/include/linux/console_splash.h b/include/linux/console_splash.h |
| 1654 |
new file mode 100644 |
| 1655 |
index 0000000..c448dd2 |
| 1656 |
--- /dev/null |
| 1657 |
+++ b/include/linux/console_splash.h |
| 1658 |
@@ -0,0 +1,13 @@ |
| 1659 |
+#ifndef _LINUX_CONSOLE_SPLASH_H_ |
| 1660 |
+#define _LINUX_CONSOLE_SPLASH_H_ 1 |
| 1661 |
+ |
| 1662 |
+/* A structure used by the framebuffer splash code (drivers/video/fbsplash.c) */ |
| 1663 |
+struct vc_splash { |
| 1664 |
+ __u8 bg_color; /* The color that is to be treated as transparent */ |
| 1665 |
+ __u8 state; /* Current splash state: 0 = off, 1 = on */ |
| 1666 |
+ __u16 tx, ty; /* Top left corner coordinates of the text field */ |
| 1667 |
+ __u16 twidth, theight; /* Width and height of the text field */ |
| 1668 |
+ char* theme; |
| 1669 |
+}; |
| 1670 |
+ |
| 1671 |
+#endif |
| 1672 |
diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h |
| 1673 |
index f8e5587..3e7f476 100644 |
| 1674 |
--- a/include/linux/console_struct.h |
| 1675 |
+++ b/include/linux/console_struct.h |
| 1676 |
@@ -14,6 +14,7 @@ |
| 1677 |
struct vt_struct; |
| 1678 |
|
| 1679 |
#define NPAR 16 |
| 1680 |
+#include <linux/console_splash.h> |
| 1681 |
|
| 1682 |
struct vc_data { |
| 1683 |
unsigned short vc_num; /* Console number */ |
| 1684 |
@@ -97,6 +98,8 @@ struct vc_data { |
| 1685 |
struct vc_data **vc_display_fg; /* [!] Ptr to var holding fg console for this display */ |
| 1686 |
unsigned long vc_uni_pagedir; |
| 1687 |
unsigned long *vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */ |
| 1688 |
+ |
| 1689 |
+ struct vc_splash vc_splash; |
| 1690 |
/* additional information is in vt_kern.h */ |
| 1691 |
}; |
| 1692 |
|
| 1693 |
diff --git a/include/linux/fb.h b/include/linux/fb.h |
| 1694 |
index 04a58f3..b8b8fab 100644 |
| 1695 |
--- a/include/linux/fb.h |
| 1696 |
+++ b/include/linux/fb.h |
| 1697 |
@@ -8,6 +8,13 @@ |
| 1698 |
#define FB_MAJOR 29 |
| 1699 |
#define FB_MAX 32 /* sufficient for now */ |
| 1700 |
|
| 1701 |
+struct fb_splash_iowrapper |
| 1702 |
+{ |
| 1703 |
+ unsigned short vc; /* Virtual console */ |
| 1704 |
+ unsigned char origin; /* Point of origin of the request */ |
| 1705 |
+ void *data; |
| 1706 |
+}; |
| 1707 |
+ |
| 1708 |
/* ioctls |
| 1709 |
0x46 is 'F' */ |
| 1710 |
#define FBIOGET_VSCREENINFO 0x4600 |
| 1711 |
@@ -35,7 +42,15 @@ |
| 1712 |
#define FBIOGET_HWCINFO 0x4616 |
| 1713 |
#define FBIOPUT_MODEINFO 0x4617 |
| 1714 |
#define FBIOGET_DISPINFO 0x4618 |
| 1715 |
- |
| 1716 |
+#define FBIOSPLASH_SETCFG _IOWR('F', 0x19, struct fb_splash_iowrapper) |
| 1717 |
+#define FBIOSPLASH_GETCFG _IOR('F', 0x1A, struct fb_splash_iowrapper) |
| 1718 |
+#define FBIOSPLASH_SETSTATE _IOWR('F', 0x1B, struct fb_splash_iowrapper) |
| 1719 |
+#define FBIOSPLASH_GETSTATE _IOR('F', 0x1C, struct fb_splash_iowrapper) |
| 1720 |
+#define FBIOSPLASH_SETPIC _IOWR('F', 0x1D, struct fb_splash_iowrapper) |
| 1721 |
+ |
| 1722 |
+#define FB_SPLASH_THEME_LEN 128 /* Maximum lenght of a theme name */ |
| 1723 |
+#define FB_SPLASH_IO_ORIG_KERNEL 0 /* Kernel ioctl origin */ |
| 1724 |
+#define FB_SPLASH_IO_ORIG_USER 1 /* User ioctl origin */ |
| 1725 |
|
| 1726 |
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */ |
| 1727 |
#define FB_TYPE_PLANES 1 /* Non interleaved planes */ |
| 1728 |
@@ -751,6 +766,9 @@ struct fb_info { |
| 1729 |
#define FBINFO_STATE_SUSPENDED 1 |
| 1730 |
u32 state; /* Hardware state i.e suspend */ |
| 1731 |
void *fbcon_par; /* fbcon use-only private area */ |
| 1732 |
+ |
| 1733 |
+ struct fb_image splash; |
| 1734 |
+ |
| 1735 |
/* From here on everything is device dependent */ |
| 1736 |
void *par; |
| 1737 |
}; |
| 1738 |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h |
| 1739 |
index 64f203c..143e3ed 100644 |
| 1740 |
--- a/include/linux/sysctl.h |
| 1741 |
+++ b/include/linux/sysctl.h |
| 1742 |
@@ -147,6 +147,7 @@ enum |
| 1743 |
KERN_RANDOMIZE=68, /* int: randomize virtual address space */ |
| 1744 |
KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */ |
| 1745 |
KERN_SPIN_RETRY=70, /* int: number of spinlock retries */ |
| 1746 |
+ KERN_FBSPLASH=71, /* string: path to fbsplash helper */ |
| 1747 |
}; |
| 1748 |
|
| 1749 |
|
| 1750 |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c |
| 1751 |
index 9990e10..47a2552 100644 |
| 1752 |
--- a/kernel/sysctl.c |
| 1753 |
+++ b/kernel/sysctl.c |
| 1754 |
@@ -86,6 +86,9 @@ extern char modprobe_path[]; |
| 1755 |
#ifdef CONFIG_HOTPLUG |
| 1756 |
extern char hotplug_path[]; |
| 1757 |
#endif |
| 1758 |
+#ifdef CONFIG_FB_SPLASH |
| 1759 |
+extern char fbsplash_path[]; |
| 1760 |
+#endif |
| 1761 |
#ifdef CONFIG_CHR_DEV_SG |
| 1762 |
extern int sg_big_buff; |
| 1763 |
#endif |
| 1764 |
@@ -404,6 +407,17 @@ static ctl_table kern_table[] = { |
| 1765 |
.strategy = &sysctl_string, |
| 1766 |
}, |
| 1767 |
#endif |
| 1768 |
+#ifdef CONFIG_FB_SPLASH |
| 1769 |
+ { |
| 1770 |
+ .ctl_name = KERN_FBSPLASH, |
| 1771 |
+ .procname = "fbsplash", |
| 1772 |
+ .data = &fbsplash_path, |
| 1773 |
+ .maxlen = KMOD_PATH_LEN, |
| 1774 |
+ .mode = 0644, |
| 1775 |
+ .proc_handler = &proc_dostring, |
| 1776 |
+ .strategy = &sysctl_string, |
| 1777 |
+ }, |
| 1778 |
+#endif |
| 1779 |
#ifdef CONFIG_CHR_DEV_SG |
| 1780 |
{ |
| 1781 |
.ctl_name = KERN_SG_BIG_BUFF, |