| Start/ | End/ | |||
| True | False | - | Line | Source |
| 1 | /* | |||
| 2 | * linux/drivers/video/fbmem.c | |||
| 3 | * | |||
| 4 | * Copyright (C) 1994 Martin Schaller | |||
| 5 | * | |||
| 6 | * 2001 - Documented with DocBook | |||
| 7 | * - Brad Douglas <brad@neruo.com> | |||
| 8 | * | |||
| 9 | * This file is subject to the terms and conditions of the GNU General Public | |||
| 10 | * License. See the file COPYING in the main directory of this archive | |||
| 11 | * for more details. | |||
| 12 | */ | |||
| 13 | ||||
| 14 | #include <linux/config.h> | |||
| 15 | #include <linux/module.h> | |||
| 16 | ||||
| 17 | #include <linux/compat.h> | |||
| 18 | #include <linux/types.h> | |||
| 19 | #include <linux/errno.h> | |||
| 20 | #include <linux/sched.h> | |||
| 21 | #include <linux/smp_lock.h> | |||
| 22 | #include <linux/kernel.h> | |||
| 23 | #include <linux/major.h> | |||
| 24 | #include <linux/slab.h> | |||
| 25 | #include <linux/mm.h> | |||
| 26 | #include <linux/mman.h> | |||
| 27 | #include <linux/tty.h> | |||
| 28 | #include <linux/init.h> | |||
| 29 | #include <linux/linux_logo.h> | |||
| 30 | #include <linux/proc_fs.h> | |||
| 31 | #include <linux/console.h> | |||
| 32 | #ifdef CONFIG_KMOD | |||
| 33 | #include <linux/kmod.h> | |||
| 34 | #endif | |||
| 35 | #include <linux/devfs_fs_kernel.h> | |||
| 36 | #include <linux/err.h> | |||
| 37 | #include <linux/kernel.h> | |||
| 38 | #include <linux/device.h> | |||
| 39 | #include <linux/efi.h> | |||
| 40 | ||||
| 41 | #if defined(__mc68000__) || defined(CONFIG_APUS) | |||
| 42 | #include <asm/setup.h> | |||
| 43 | #endif | |||
| 44 | ||||
| 45 | #include <asm/io.h> | |||
| 46 | #include <asm/uaccess.h> | |||
| 47 | #include <asm/page.h> | |||
| 48 | #include <asm/pgtable.h> | |||
| 49 | ||||
| 50 | #include <linux/fb.h> | |||
| 51 | ||||
| 52 | /* | |||
| 53 | * Frame buffer device initialization and setup routines | |||
| 54 | */ | |||
| 55 | ||||
| 56 | #define FBPIXMAPSIZE (1024 * 8) | |||
| 57 | ||||
| 58 | static struct notifier_block *fb_notifier_list; | |||
| 59 | struct fb_info *registered_fb[FB_MAX]; | |||
| 60 | int num_registered_fb; | |||
| 61 | ||||
| 62 | /* | |||
| 63 | * Helpers | |||
| 64 | */ | |||
| 65 | ||||
| 907974 | 0 | 66 | int fb_get_color_depth(struct fb_var_screeninfo *var, | |
| 67 | struct fb_fix_screeninfo *fix) | |||
| 68 | { | |||
| 69 | int depth = 0; | |||
| 70 | ||||
| 71 | if (fix->visual == FB_VISUAL_MONO01 || | |||
| 0 | 907974 | - | 72 | fix->visual == FB_VISUAL_MONO10) |
| 0 | - | 72 | T || _ | |
| 0 | - | 72 | F || T | |
| 907974 | 72 | F || F | ||
| 73 | depth = 1; | |||
| 74 | else { | |||
| 75 | if (var->green.length == var->blue.length && | |||
| 76 | var->green.length == var->red.length && | |||
| 77 | var->green.offset == var->blue.offset && | |||
| 907974 | 0 | - | 78 | var->green.offset == var->red.offset) |
| 907974 | 78 | T && T && T && T | ||
| 0 | - | 78 | T && T && T && F | |
| 0 | - | 78 | T && T && F && _ | |
| 0 | - | 78 | T && F && _ && _ | |
| 0 | - | 78 | F && _ && _ && _ | |
| 79 | depth = var->green.length; | |||
| 80 | else | |||
| 81 | depth = var->green.length + var->red.length + | |||
| 82 | var->blue.length; | |||
| 83 | } | |||
| 84 | ||||
| 907974 | 85 | return depth; | ||
| 86 | } | |||
| 87 | EXPORT_SYMBOL(fb_get_color_depth); | |||
| 88 | ||||
| 89 | /* | |||
| 90 | * Data padding functions. | |||
| 91 | */ | |||
| 49855 | 49855 | 92 | void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) | |
| 93 | { | |||
| 94 | __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height); | |||
| 95 | } | |||
| 96 | EXPORT_SYMBOL(fb_pad_aligned_buffer); | |||
| 97 | ||||
| 0 | 0 | - | 98 | void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, |
| 99 | u32 shift_high, u32 shift_low, u32 mod) | |||
| 100 | { | |||
| 101 | u8 mask = (u8) (0xfff << shift_high), tmp; | |||
| 102 | int i, j; | |||
| 103 | ||||
| 0 | 0 | - | 104 | for (i = height; i--; ) { |
| 0 | 0 | - | 105 | for (j = 0; j < idx; j++) { |
| 106 | tmp = dst[j]; | |||
| 107 | tmp &= mask; | |||
| 108 | tmp |= *src >> shift_low; | |||
| 109 | dst[j] = tmp; | |||
| 110 | tmp = *src << shift_high; | |||
| 111 | dst[j+1] = tmp; | |||
| 112 | src++; | |||
| 113 | } | |||
| 114 | tmp = dst[idx]; | |||
| 115 | tmp &= mask; | |||
| 116 | tmp |= *src >> shift_low; | |||
| 117 | dst[idx] = tmp; | |||
| 0 | 0 | - | 118 | if (shift_high < mod) { |
| 119 | tmp = *src << shift_high; | |||
| 120 | dst[idx+1] = tmp; | |||
| 121 | } | |||
| 122 | src++; | |||
| 123 | dst += d_pitch; | |||
| 124 | } | |||
| 125 | } | |||
| 126 | EXPORT_SYMBOL(fb_pad_unaligned_buffer); | |||
| 127 | ||||
| 128 | /* | |||
| 129 | * we need to lock this section since fb_cursor | |||
| 130 | * may use fb_imageblit() | |||
| 131 | */ | |||
| 302579 | 0 | 132 | char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size) | |
| 133 | { | |||
| 134 | u32 align = buf->buf_align - 1, offset; | |||
| 135 | char *addr = buf->addr; | |||
| 136 | ||||
| 137 | /* If IO mapped, we need to sync before access, no sharing of | |||
| 138 | * the pixmap is done | |||
| 139 | */ | |||
| 0 | 302579 | - | 140 | if (buf->flags & FB_PIXMAP_IO) { |
| 0 | 0 | - | 141 | if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC)) |
| 0 | - | 141 | T && (T) | |
| 0 | - | 141 | T && (F) | |
| 0 | - | 141 | F && (_) | |
| 142 | info->fbops->fb_sync(info); | |||
| 0 | - | 143 | return addr; | |
| 144 | } | |||
| 145 | ||||
| 146 | /* See if we fit in the remaining pixmap space */ | |||
| 147 | offset = buf->offset + align; | |||
| 148 | offset &= ~align; | |||
| 6145 | 296434 | 149 | if (offset + size > buf->size) { | |
| 150 | /* We do not fit. In order to be able to re-use the buffer, | |||
| 151 | * we must ensure no asynchronous DMA'ing or whatever operation | |||
| 152 | * is in progress, we sync for that. | |||
| 153 | */ | |||
| 0 | 6145 | - | 154 | if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC)) |
| 0 | - | 154 | T && (T) | |
| 6145 | 154 | T && (F) | ||
| 0 | - | 154 | F && (_) | |
| 155 | info->fbops->fb_sync(info); | |||
| 156 | offset = 0; | |||
| 157 | } | |||
| 158 | buf->offset = offset + size; | |||
| 159 | addr += offset; | |||
| 160 | ||||
| 302579 | 161 | return addr; | ||
| 162 | } | |||
| 163 | ||||
| 164 | #ifdef CONFIG_LOGO | |||
| 165 | #include <linux/linux_logo.h> | |||
| 166 | ||||
| 0 | 0 | - | 167 | static inline unsigned safe_shift(unsigned d, int n) |
| 168 | { | |||
| 169 | return n < 0 ? d >> -n : d << n; | |||
| 0 | 0 | - | 169 | ternary-?: n < 0 |
| 0 | - | 169 | return n < 0 ? d >> - n : d << n | |
| 170 | } | |||
| 171 | ||||
| 6 | 6 | 172 | static void fb_set_logocmap(struct fb_info *info, | |
| 173 | const struct linux_logo *logo) | |||
| 174 | { | |||
| 175 | struct fb_cmap palette_cmap; | |||
| 176 | u16 palette_green[16]; | |||
| 177 | u16 palette_blue[16]; | |||
| 178 | u16 palette_red[16]; | |||
| 179 | int i, j, n; | |||
| 180 | const unsigned char *clut = logo->clut; | |||
| 181 | ||||
| 182 | palette_cmap.start = 0; | |||
| 183 | palette_cmap.len = 16; | |||
| 184 | palette_cmap.red = palette_red; | |||
| 185 | palette_cmap.green = palette_green; | |||
| 186 | palette_cmap.blue = palette_blue; | |||
| 187 | palette_cmap.transp = NULL; | |||
| 188 | ||||
| 72 | 6 | 189 | for (i = 0; i < logo->clutsize; i += n) { | |
| 190 | n = logo->clutsize - i; | |||
| 191 | /* palette_cmap provides space for only 16 colors at once */ | |||
| 66 | 6 | 192 | if (n > 16) | |
| 193 | n = 16; | |||
| 194 | palette_cmap.start = 32 + i; | |||
| 195 | palette_cmap.len = n; | |||
| 1122 | 72 | 196 | for (j = 0; j < n; ++j) { | |
| 197 | palette_cmap.red[j] = clut[0] << 8 | clut[0]; | |||
| 198 | palette_cmap.green[j] = clut[1] << 8 | clut[1]; | |||
| 199 | palette_cmap.blue[j] = clut[2] << 8 | clut[2]; | |||
| 200 | clut += 3; | |||
| 201 | } | |||
| 202 | fb_set_cmap(&palette_cmap, info); | |||
| 203 | } | |||
| 204 | } | |||
| 205 | ||||
| 0 | 0 | - | 206 | static void fb_set_logo_truepalette(struct fb_info *info, |
| 207 | const struct linux_logo *logo, | |||
| 208 | u32 *palette) | |||
| 209 | { | |||
| 210 | unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; | |||
| 211 | unsigned char redmask, greenmask, bluemask; | |||
| 212 | int redshift, greenshift, blueshift; | |||
| 213 | int i; | |||
| 214 | const unsigned char *clut = logo->clut; | |||
| 215 | ||||
| 216 | /* | |||
| 217 | * We have to create a temporary palette since console palette is only | |||
| 218 | * 16 colors long. | |||
| 219 | */ | |||
| 220 | /* Bug: Doesn't obey msb_right ... (who needs that?) */ | |||
| 221 | redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8]; | |||
| 0 | 0 | - | 221 | ternary-?: info -> var . red . length < 8 |
| 222 | greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8]; | |||
| 0 | 0 | - | 222 | ternary-?: info -> var . green . length < 8 |
| 223 | bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8]; | |||
| 0 | 0 | - | 223 | ternary-?: info -> var . blue . length < 8 |
| 224 | redshift = info->var.red.offset - (8 - info->var.red.length); | |||
| 225 | greenshift = info->var.green.offset - (8 - info->var.green.length); | |||
| 226 | blueshift = info->var.blue.offset - (8 - info->var.blue.length); | |||
| 227 | ||||
| 0 | 0 | - | 228 | for ( i = 0; i < logo->clutsize; i++) { |
| 229 | palette[i+32] = (safe_shift((clut[0] & redmask), redshift) | | |||
| 230 | safe_shift((clut[1] & greenmask), greenshift) | | |||
| 231 | safe_shift((clut[2] & bluemask), blueshift)); | |||
| 232 | clut += 3; | |||
| 233 | } | |||
| 234 | } | |||
| 235 | ||||
| 0 | 0 | - | 236 | static void fb_set_logo_directpalette(struct fb_info *info, |
| 237 | const struct linux_logo *logo, | |||
| 238 | u32 *palette) | |||
| 239 | { | |||
| 240 | int redshift, greenshift, blueshift; | |||
| 241 | int i; | |||
| 242 | ||||
| 243 | redshift = info->var.red.offset; | |||
| 244 | greenshift = info->var.green.offset; | |||
| 245 | blueshift = info->var.blue.offset; | |||
| 246 | ||||
| 0 | 0 | - | 247 | for (i = 32; i < logo->clutsize; i++) |
| 248 | palette[i] = i << redshift | i << greenshift | i << blueshift; | |||
| 249 | } | |||
| 250 | ||||
| 0 | 0 | - | 251 | static void fb_set_logo(struct fb_info *info, |
| 252 | const struct linux_logo *logo, u8 *dst, | |||
| 253 | int depth) | |||
| 254 | { | |||
| 255 | int i, j, k; | |||
| 256 | const u8 *src = logo->data; | |||
| 257 | u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; | |||
| 0 | 0 | - | 257 | ternary-?: ( info -> fix . visual == 0 ) |
| 258 | u8 fg = 1, d; | |||
| 259 | ||||
| 0 | 0 | - | 260 | if (fb_get_color_depth(&info->var, &info->fix) == 3) |
| 261 | fg = 7; | |||
| 262 | ||||
| 263 | if (info->fix.visual == FB_VISUAL_MONO01 || | |||
| 0 | 0 | - | 264 | info->fix.visual == FB_VISUAL_MONO10) |
| 0 | - | 264 | T || _ | |
| 0 | - | 264 | F || T | |
| 0 | - | 264 | F || F | |
| 265 | fg = ~((u8) (0xfff << info->var.green.length)); | |||
| 266 | ||||
| 267 | switch (depth) { | |||
| 0 | - | 268 | case 4: | |
| 0 | 0 | - | 269 | for (i = 0; i < logo->height; i++) |
| 0 | 0 | - | 270 | for (j = 0; j < logo->width; src++) { |
| 271 | *dst++ = *src >> 4; | |||
| 272 | j++; | |||
| 0 | 0 | - | 273 | if (j < logo->width) { |
| 274 | *dst++ = *src & 0x0f; | |||
| 275 | j++; | |||
| 276 | } | |||
| 277 | } | |||
| 0 | - | 278 | break; | |
| 0 | - | 279 | case 1: | |
| 0 | 0 | - | 280 | for (i = 0; i < logo->height; i++) { |
| 0 | 0 | - | 281 | for (j = 0; j < logo->width; src++) { |
| 282 | d = *src ^ xor; | |||
| 0 | 0 | - | 283 | for (k = 7; k >= 0; k--) { |
| 284 | *dst++ = ((d >> k) & 1) ? fg : 0; | |||
| 0 | 0 | - | 284 | ternary-?: ( ( d >> k ) & 1 ) |
| 285 | j++; | |||
| 286 | } | |||
| 287 | } | |||
| 288 | } | |||
| 0 | - | 289 | break; | |
| 290 | } | |||
| 291 | } | |||
| 292 | ||||
| 293 | /* | |||
| 294 | * Three (3) kinds of logo maps exist. linux_logo_clut224 (>16 colors), | |||
| 295 | * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors). Depending on | |||
| 296 | * the visual format and color depth of the framebuffer, the DAC, the | |||
| 297 | * pseudo_palette, and the logo data will be adjusted accordingly. | |||
| 298 | * | |||
| 299 | * Case 1 - linux_logo_clut224: | |||
| 300 | * Color exceeds the number of console colors (16), thus we set the hardware DAC | |||
| 301 | * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set. | |||
| 302 | * | |||
| 303 | * For visuals that require color info from the pseudo_palette, we also construct | |||
| 304 | * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags | |||
| 305 | * will be set. | |||
| 306 | * | |||
| 307 | * Case 2 - linux_logo_vga16: | |||
| 308 | * The number of colors just matches the console colors, thus there is no need | |||
| 309 | * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie, | |||
| 310 | * each byte contains color information for two pixels (upper and lower nibble). | |||
| 311 | * To be consistent with fb_imageblit() usage, we therefore separate the two | |||
| 312 | * nibbles into separate bytes. The "depth" flag will be set to 4. | |||
| 313 | * | |||
| 314 | * Case 3 - linux_logo_mono: | |||
| 315 | * This is similar with Case 2. Each byte contains information for 8 pixels. | |||
| 316 | * We isolate each bit and expand each into a byte. The "depth" flag will | |||
| 317 | * be set to 1. | |||
| 318 | */ | |||
| 319 | static struct logo_data { | |||
| 320 | int depth; | |||
| 321 | int needs_directpalette; | |||
| 322 | int needs_truepalette; | |||
| 323 | int needs_cmapreset; | |||
| 324 | const struct linux_logo *logo; | |||
| 325 | } fb_logo; | |||
| 326 | ||||
| 0 | 0 | - | 327 | static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) |
| 328 | { | |||
| 329 | u32 size = width * height, i; | |||
| 330 | ||||
| 331 | out += size - 1; | |||
| 332 | ||||
| 0 | 0 | - | 333 | for (i = size; i--; ) |
| 334 | *out-- = *in++; | |||
| 335 | } | |||
| 336 | ||||
| 0 | 0 | - | 337 | static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) |
| 338 | { | |||
| 339 | int i, j, w = width - 1; | |||
| 340 | ||||
| 0 | 0 | - | 341 | for (i = 0; i < height; i++) |
| 0 | 0 | - | 342 | for (j = 0; j < width; j++) |
| 343 | out[height * j + w - i] = *in++; | |||
| 344 | } | |||
| 345 | ||||
| 0 | 0 | - | 346 | static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) |
| 347 | { | |||
| 348 | int i, j, w = width - 1; | |||
| 349 | ||||
| 0 | 0 | - | 350 | for (i = 0; i < height; i++) |
| 0 | 0 | - | 351 | for (j = 0; j < width; j++) |
| 352 | out[height * (w - j) + i] = *in++; | |||
| 353 | } | |||
| 354 | ||||
| 0 | 0 | - | 355 | static void fb_rotate_logo(struct fb_info *info, u8 *dst, |
| 356 | struct fb_image *image, int rotate) | |||
| 357 | { | |||
| 358 | u32 tmp; | |||
| 359 | ||||
| 0 | 0 | - | 360 | if (rotate == FB_ROTATE_UD) { |
| 361 | image->dx = info->var.xres - image->width; | |||
| 362 | image->dy = info->var.yres - image->height; | |||
| 363 | fb_rotate_logo_ud(image->data, dst, image->width, | |||
| 364 | image->height); | |||
| 0 | 0 | - | 365 | } else if (rotate == FB_ROTATE_CW) { |
| 366 | tmp = image->width; | |||
| 367 | image->width = image->height; | |||
| 368 | image->height = tmp; | |||
| 369 | image->dx = info->var.xres - image->height; | |||
| 370 | fb_rotate_logo_cw(image->data, dst, image->width, | |||
| 371 | image->height); | |||
| 0 | 0 | - | 372 | } else if (rotate == FB_ROTATE_CCW) { |
| 373 | tmp = image->width; | |||
| 374 | image->width = image->height; | |||
| 375 | image->height = tmp; | |||
| 376 | image->dy = info->var.yres - image->width; | |||
| 377 | fb_rotate_logo_ccw(image->data, dst, image->width, | |||
| 378 | image->height); | |||
| 379 | } | |||
| 380 | ||||
| 381 | image->data = dst; | |||
| 382 | } | |||
| 383 | ||||
| 6 | 6 | 384 | static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, | |
| 385 | int rotate) | |||
| 386 | { | |||
| 387 | int x; | |||
| 388 | ||||
| 6 | 0 | - | 389 | if (rotate == FB_ROTATE_UR) { |
| 390 | for (x = 0; x < num_online_cpus() && | |||
| 391 | x * (fb_logo.logo->width + 8) <= | |||
| 6 | 6 | 392 | info->var.xres - fb_logo.logo->width; x++) { | |
| 6 | 392 | T && T | ||
| 0 | - | 392 | T && F | |
| 6 | 392 | F && _ | ||
| 393 | info->fbops->fb_imageblit(info, image); | |||
| 394 | image->dx += fb_logo.logo->width + 8; | |||
| 395 | } | |||
| 0 | 0 | - | 396 | } else if (rotate == FB_ROTATE_UD) { |
| 397 | for (x = 0; x < num_online_cpus() && | |||
| 398 | x * (fb_logo.logo->width + 8) <= | |||
| 0 | 0 | - | 399 | info->var.xres - fb_logo.logo->width; x++) { |
| 0 | - | 399 | T && T | |
| 0 | - | 399 | T && F | |
| 0 | - | 399 | F && _ | |
| 400 | info->fbops->fb_imageblit(info, image); | |||
| 401 | image->dx -= fb_logo.logo->width + 8; | |||
| 402 | } | |||
| 0 | 0 | - | 403 | } else if (rotate == FB_ROTATE_CW) { |
| 404 | for (x = 0; x < num_online_cpus() && | |||
| 405 | x * (fb_logo.logo->width + 8) <= | |||
| 0 | 0 | - | 406 | info->var.yres - fb_logo.logo->width; x++) { |
| 0 | - | 406 | T && T | |
| 0 | - | 406 | T && F | |
| 0 | - | 406 | F && _ | |
| 407 | info->fbops->fb_imageblit(info, image); | |||
| 408 | image->dy += fb_logo.logo->width + 8; | |||
| 409 | } | |||
| 0 | 0 | - | 410 | } else if (rotate == FB_ROTATE_CCW) { |
| 411 | for (x = 0; x < num_online_cpus() && | |||
| 412 | x * (fb_logo.logo->width + 8) <= | |||
| 0 | 0 | - | 413 | info->var.yres - fb_logo.logo->width; x++) { |
| 0 | - | 413 | T && T | |
| 0 | - | 413 | T && F | |
| 0 | - | 413 | F && _ | |
| 414 | info->fbops->fb_imageblit(info, image); | |||
| 415 | image->dy -= fb_logo.logo->width + 8; | |||
| 416 | } | |||
| 417 | } | |||
| 418 | } | |||
| 419 | ||||
| 6 | 0 | 420 | int fb_prepare_logo(struct fb_info *info, int rotate) | |
| 421 | { | |||
| 422 | int depth = fb_get_color_depth(&info->var, &info->fix); | |||
| 423 | int yres; | |||
| 424 | ||||
| 425 | memset(&fb_logo, 0, sizeof(struct logo_data)); | |||
| 426 | ||||
| 0 | 6 | - | 427 | if (info->flags & FBINFO_MISC_TILEBLITTING) |
| 0 | - | 428 | return 0; | |
| 429 | ||||
| 0 | 6 | - | 430 | if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { |
| 431 | depth = info->var.blue.length; | |||
| 0 | 0 | - | 432 | if (info->var.red.length < depth) |
| 433 | depth = info->var.red.length; | |||
| 0 | 0 | - | 434 | if (info->var.green.length < depth) |
| 435 | depth = info->var.green.length; | |||
| 436 | } | |||
| 437 | ||||
| 6 | 0 | - | 438 | if (depth >= 8) { |
| 439 | switch (info->fix.visual) { | |||
| 0 | - | 440 | case FB_VISUAL_TRUECOLOR: | |
| 441 | fb_logo.needs_truepalette = 1; | |||
| 0 | - | 442 | break; | |
| 0 | - | 443 | case FB_VISUAL_DIRECTCOLOR: | |
| 444 | fb_logo.needs_directpalette = 1; | |||
| 445 | fb_logo.needs_cmapreset = 1; | |||
| 0 | - | 446 | break; | |
| 6 | 447 | case FB_VISUAL_PSEUDOCOLOR: | ||
| 448 | fb_logo.needs_cmapreset = 1; | |||
| 6 | 449 | break; | ||
| 450 | } | |||
| 451 | } | |||
| 452 | ||||
| 453 | /* Return if no suitable logo was found */ | |||
| 454 | fb_logo.logo = fb_find_logo(depth); | |||
| 455 | ||||
| 0 | 6 | - | 456 | if (!fb_logo.logo) { |
| 0 | - | 457 | return 0; | |
| 458 | } | |||
| 459 | ||||
| 6 | 0 | - | 460 | if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) |
| 6 | 460 | T || _ | ||
| 0 | - | 460 | F || T | |
| 0 | - | 460 | F || F | |
| 461 | yres = info->var.yres; | |||
| 462 | else | |||
| 463 | yres = info->var.xres; | |||
| 464 | ||||
| 0 | 6 | - | 465 | if (fb_logo.logo->height > yres) { |
| 466 | fb_logo.logo = NULL; | |||
| 0 | - | 467 | return 0; | |
| 468 | } | |||
| 469 | ||||
| 470 | /* What depth we asked for might be different from what we get */ | |||
| 6 | 0 | - | 471 | if (fb_logo.logo->type == LINUX_LOGO_CLUT224) |
| 472 | fb_logo.depth = 8; | |||
| 0 | 0 | - | 473 | else if (fb_logo.logo->type == LINUX_LOGO_VGA16) |
| 474 | fb_logo.depth = 4; | |||
| 475 | else | |||
| 476 | fb_logo.depth = 1; | |||
| 6 | 477 | return fb_logo.logo->height; | ||
| 478 | } | |||
| 479 | ||||
| 6 | 0 | 480 | int fb_show_logo(struct fb_info *info, int rotate) | |
| 481 | { | |||
| 482 | u32 *palette = NULL, *saved_pseudo_palette = NULL; | |||
| 483 | unsigned char *logo_new = NULL, *logo_rotate = NULL; | |||
| 484 | struct fb_image image; | |||
| 485 | ||||
| 486 | /* R | |||