aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbmem.c')
-rw-r--r--drivers/video/fbmem.c130
1 files changed, 117 insertions, 13 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index e2667ddab3f1..7a2a8fa50b3b 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -323,9 +323,103 @@ static struct logo_data {
323 const struct linux_logo *logo; 323 const struct linux_logo *logo;
324} fb_logo; 324} fb_logo;
325 325
326int fb_prepare_logo(struct fb_info *info) 326static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
327{
328 u32 size = width * height, i;
329
330 out += size - 1;
331
332 for (i = size; i--; )
333 *out-- = *in++;
334}
335
336static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
337{
338 int i, j, w = width - 1;
339
340 for (i = 0; i < height; i++)
341 for (j = 0; j < width; j++)
342 out[height * j + w - i] = *in++;
343}
344
345static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
346{
347 int i, j, w = width - 1;
348
349 for (i = 0; i < height; i++)
350 for (j = 0; j < width; j++)
351 out[height * (w - j) + i] = *in++;
352}
353
354static void fb_rotate_logo(struct fb_info *info, u8 *dst,
355 struct fb_image *image, int rotate)
356{
357 u32 tmp;
358
359 if (rotate == FB_ROTATE_UD) {
360 image->dx = info->var.xres - image->width;
361 image->dy = info->var.yres - image->height;
362 fb_rotate_logo_ud(image->data, dst, image->width,
363 image->height);
364 } else if (rotate == FB_ROTATE_CW) {
365 tmp = image->width;
366 image->width = image->height;
367 image->height = tmp;
368 image->dx = info->var.xres - image->height;
369 fb_rotate_logo_cw(image->data, dst, image->width,
370 image->height);
371 } else if (rotate == FB_ROTATE_CCW) {
372 tmp = image->width;
373 image->width = image->height;
374 image->height = tmp;
375 image->dy = info->var.yres - image->width;
376 fb_rotate_logo_ccw(image->data, dst, image->width,
377 image->height);
378 }
379
380 image->data = dst;
381}
382
383static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
384 int rotate)
385{
386 int x;
387
388 if (rotate == FB_ROTATE_UR) {
389 for (x = 0; x < num_online_cpus() &&
390 x * (fb_logo.logo->width + 8) <=
391 info->var.xres - fb_logo.logo->width; x++) {
392 info->fbops->fb_imageblit(info, image);
393 image->dx += fb_logo.logo->width + 8;
394 }
395 } else if (rotate == FB_ROTATE_UD) {
396 for (x = 0; x < num_online_cpus() &&
397 x * (fb_logo.logo->width + 8) <=
398 info->var.xres - fb_logo.logo->width; x++) {
399 info->fbops->fb_imageblit(info, image);
400 image->dx -= fb_logo.logo->width + 8;
401 }
402 } else if (rotate == FB_ROTATE_CW) {
403 for (x = 0; x < num_online_cpus() &&
404 x * (fb_logo.logo->width + 8) <=
405 info->var.yres - fb_logo.logo->width; x++) {
406 info->fbops->fb_imageblit(info, image);
407 image->dy += fb_logo.logo->width + 8;
408 }
409 } else if (rotate == FB_ROTATE_CCW) {
410 for (x = 0; x < num_online_cpus() &&
411 x * (fb_logo.logo->width + 8) <=
412 info->var.yres - fb_logo.logo->width; x++) {
413 info->fbops->fb_imageblit(info, image);
414 image->dy -= fb_logo.logo->width + 8;
415 }
416 }
417}
418
419int fb_prepare_logo(struct fb_info *info, int rotate)
327{ 420{
328 int depth = fb_get_color_depth(&info->var, &info->fix); 421 int depth = fb_get_color_depth(&info->var, &info->fix);
422 int yres;
329 423
330 memset(&fb_logo, 0, sizeof(struct logo_data)); 424 memset(&fb_logo, 0, sizeof(struct logo_data));
331 425
@@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info)
358 /* Return if no suitable logo was found */ 452 /* Return if no suitable logo was found */
359 fb_logo.logo = fb_find_logo(depth); 453 fb_logo.logo = fb_find_logo(depth);
360 454
361 if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { 455 if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
456 yres = info->var.yres;
457 else
458 yres = info->var.xres;
459
460 if (fb_logo.logo && fb_logo.logo->height > yres) {
362 fb_logo.logo = NULL; 461 fb_logo.logo = NULL;
363 return 0; 462 return 0;
364 } 463 }
464
365 /* What depth we asked for might be different from what we get */ 465 /* What depth we asked for might be different from what we get */
366 if (fb_logo.logo->type == LINUX_LOGO_CLUT224) 466 if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
367 fb_logo.depth = 8; 467 fb_logo.depth = 8;
@@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info)
372 return fb_logo.logo->height; 472 return fb_logo.logo->height;
373} 473}
374 474
375int fb_show_logo(struct fb_info *info) 475int fb_show_logo(struct fb_info *info, int rotate)
376{ 476{
377 u32 *palette = NULL, *saved_pseudo_palette = NULL; 477 u32 *palette = NULL, *saved_pseudo_palette = NULL;
378 unsigned char *logo_new = NULL; 478 unsigned char *logo_new = NULL, *logo_rotate = NULL;
379 struct fb_image image; 479 struct fb_image image;
380 int x;
381 480
382 /* Return if the frame buffer is not mapped or suspended */ 481 /* Return if the frame buffer is not mapped or suspended */
383 if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) 482 if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
@@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info)
417 fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); 516 fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
418 } 517 }
419 518
519 image.dx = 0;
520 image.dy = 0;
420 image.width = fb_logo.logo->width; 521 image.width = fb_logo.logo->width;
421 image.height = fb_logo.logo->height; 522 image.height = fb_logo.logo->height;
422 image.dy = 0;
423 523
424 for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && 524 if (rotate) {
425 x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { 525 logo_rotate = kmalloc(fb_logo.logo->width *
426 image.dx = x; 526 fb_logo.logo->height, GFP_KERNEL);
427 info->fbops->fb_imageblit(info, &image); 527 if (logo_rotate)
528 fb_rotate_logo(info, logo_rotate, &image, rotate);
428 } 529 }
429 530
531 fb_do_show_logo(info, &image, rotate);
532
430 kfree(palette); 533 kfree(palette);
431 if (saved_pseudo_palette != NULL) 534 if (saved_pseudo_palette != NULL)
432 info->pseudo_palette = saved_pseudo_palette; 535 info->pseudo_palette = saved_pseudo_palette;
433 kfree(logo_new); 536 kfree(logo_new);
537 kfree(logo_rotate);
434 return fb_logo.logo->height; 538 return fb_logo.logo->height;
435} 539}
436#else 540#else
437int fb_prepare_logo(struct fb_info *info) { return 0; } 541int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
438int fb_show_logo(struct fb_info *info) { return 0; } 542int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
439#endif /* CONFIG_LOGO */ 543#endif /* CONFIG_LOGO */
440 544
441static int fbmem_read_proc(char *buf, char **start, off_t offset, 545static int fbmem_read_proc(char *buf, char **start, off_t offset,