lcd 2
时间:2010-04-21 来源:wulinnm
288
289 /*
290 * Three (3) kinds of logo maps exist. linux_logo_clut224 (>16 colors),
291 * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors). Depending on
292 * the visual format and color depth of the framebuffer, the DAC, the
293 * pseudo_palette, and the logo data will be adjusted accordingly.
294 *
295 * Case 1 - linux_logo_clut224:
296 * Color exceeds the number of console colors (16), thus we set the hardware DAC
297 * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
298 *
299 * For visuals that require color info from the pseudo_palette, we also construct
300 * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
301 * will be set.
302 *
303 * Case 2 - linux_logo_vga16:
304 * The number of colors just matches the console colors, thus there is no need
305 * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
306 * each byte contains color information for two pixels (upper and lower nibble).
307 * To be consistent with fb_imageblit() usage, we therefore separate the two
308 * nibbles into separate bytes. The "depth" flag will be set to 4.
309 *
310 * Case 3 - linux_logo_mono:
311 * This is similar with Case 2. Each byte contains information for 8 pixels.
312 * We isolate each bit and expand each into a byte. The "depth" flag will
313 * be set to 1.
314 */
315 static struct logo_data {
316 int depth;
317 int needs_directpalette;
318 int needs_truepalette;
319 int needs_cmapreset;
320 const struct linux_logo *logo;
321 } fb_logo __read_mostly;
322
323 static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
324 {
325 u32 size = width * height, i;
326
327 out += size - 1;
328
329 for (i = size; i--; )
330 *out-- = *in++;
331 }
332
333 static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
334 {
335 int i, j, h = height - 1;
336
337 for (i = 0; i < height; i++)
338 for (j = 0; j < width; j++)
339 out[height * j + h - i] = *in++;
340 }
341
342 static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
343 {
344 int i, j, w = width - 1;
345
346 for (i = 0; i < height; i++)
347 for (j = 0; j < width; j++)
348 out[height * (w - j) + i] = *in++;
349 }
350
351 static void fb_rotate_logo(struct fb_info *info, u8 *dst,
352 struct fb_image *image, int rotate)
353 {
354 u32 tmp;
355
356 if (rotate == FB_ROTATE_UD) {
357 fb_rotate_logo_ud(image->data, dst, image->width,
358 image->height);
359 image->dx = info->var.xres - image->width - image->dx;
360 image->dy = info->var.yres - image->height - image->dy;
361 } else if (rotate == FB_ROTATE_CW) {
362 fb_rotate_logo_cw(image->data, dst, image->width,
363 image->height);
364 tmp = image->width;
365 image->width = image->height;
366 image->height = tmp;
367 tmp = image->dy;
368 image->dy = image->dx;
369 image->dx = info->var.xres - image->width - tmp;
370 } else if (rotate == FB_ROTATE_CCW) {
371 fb_rotate_logo_ccw(image->data, dst, image->width,
372 image->height);
373 tmp = image->width;
374 image->width = image->height;
375 image->height = tmp;
376 tmp = image->dx;
377 image->dx = image->dy;
378 image->dy = info->var.yres - image->height - tmp;
379 }
380
381 image->data = dst;
382 }
383
384 static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
385 int rotate, unsigned int num)
386 {
387 unsigned int x;
388
389 if (rotate == FB_ROTATE_UR) {
390 for (x = 0;
391 x < num && image->dx + image->width <= info->var.xres;
392 x++) {
393 info->fbops->fb_imageblit(info, image);
394 image->dx += image->width + 8;
395 }
396 } else if (rotate == FB_ROTATE_UD) {
397 for (x = 0; x < num && image->dx >= 0; x++) {
398 info->fbops->fb_imageblit(info, image);
399 image->dx -= image->width + 8;
400 }
401 } else if (rotate == FB_ROTATE_CW) {
402 for (x = 0;
403 x < num && image->dy + image->height <= info->var.yres;
404 x++) {
405 info->fbops->fb_imageblit(info, image);
406 image->dy += image->height + 8;
407 }
408 } else if (rotate == FB_ROTATE_CCW) {
409 for (x = 0; x < num && image->dy >= 0; x++) {
410 info->fbops->fb_imageblit(info, image);
411 image->dy -= image->height + 8;
412 }
413 }
414 }
415
416 static int fb_show_logo_line(struct fb_info *info, int rotate,
417 const struct linux_logo *logo, int y,
418 unsigned int n)
419 {
420 u32 *palette = NULL, *saved_pseudo_palette = NULL;
421 unsigned char *logo_new = NULL, *logo_rotate = NULL;
422 struct fb_image image;
423
424 /* Return if the frame buffer is not mapped or suspended */
425 if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
426 info->flags & FBINFO_MODULE)
427 return 0;
428
429 image.depth = 8;
430 image.data = logo->data;
431
432 if (fb_logo.needs_cmapreset)
433 fb_set_logocmap(info, logo);
434
435 if (fb_logo.needs_truepalette ||
436 fb_logo.needs_directpalette) {
437 palette = kmalloc(256 * 4, GFP_KERNEL);
438 if (palette == NULL)
439 return 0;
440
441 if (fb_logo.needs_truepalette)
442 fb_set_logo_truepalette(info, logo, palette);
443 else
444 fb_set_logo_directpalette(info, logo, palette);
445
446 saved_pseudo_palette = info->pseudo_palette;
447 info->pseudo_palette = palette;
448 }
449
450 if (fb_logo.depth <= 4) {
451 logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
452 if (logo_new == NULL) {
453 kfree(palette);
454 if (saved_pseudo_palette)
455 info->pseudo_palette = saved_pseudo_palette;
456 return 0;
457 }
458 image.data = logo_new;
459 fb_set_logo(info, logo, logo_new, fb_logo.depth);
460 }
461
462 image.dx = 0;
463 image.dy = y;
464 image.width = logo->width;
465 image.height = logo->height;
466
467 if (rotate) {
468 logo_rotate = kmalloc(logo->width *
469 logo->height, GFP_KERNEL);
470 if (logo_rotate)
471 fb_rotate_logo(info, logo_rotate, &image, rotate);
472 }
473
474 fb_do_show_logo(info, &image, rotate, n);
475
476 kfree(palette);
477 if (saved_pseudo_palette != NULL)
478 info->pseudo_palette = saved_pseudo_palette;
479 kfree(logo_new);
480 kfree(logo_rotate);
481 return logo->height;
482 }
483
484
485 #ifdef CONFIG_FB_LOGO_EXTRA
486
487 #define FB_LOGO_EX_NUM_MAX 10
488 static struct logo_data_extra {
489 const struct linux_logo *logo;
490 unsigned int n;
491 } fb_logo_ex[FB_LOGO_EX_NUM_MAX];
492 static unsigned int fb_logo_ex_num;
493
494 void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
495 {
496 if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
497 return;
498
499 fb_logo_ex[fb_logo_ex_num].logo = logo;
500 fb_logo_ex[fb_logo_ex_num].n = n;
501 fb_logo_ex_num++;
502 }
503
504 static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
505 unsigned int yres)
506 {
507 unsigned int i;
508
509 /* FIXME: logo_ex supports only truecolor fb. */
510 if (info->fix.visual != FB_VISUAL_TRUECOLOR)
511 fb_logo_ex_num = 0;
512
513 for (i = 0; i < fb_logo_ex_num; i++) {
514 height += fb_logo_ex[i].logo->height;
515 if (height > yres) {
516 height -= fb_logo_ex[i].logo->height;
517 fb_logo_ex_num = i;
518 break;
519 }
520 }
521 return height;
522 }
523
289 /*
290 * Three (3) kinds of logo maps exist. linux_logo_clut224 (>16 colors),
291 * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors). Depending on
292 * the visual format and color depth of the framebuffer, the DAC, the
293 * pseudo_palette, and the logo data will be adjusted accordingly.
294 *
295 * Case 1 - linux_logo_clut224:
296 * Color exceeds the number of console colors (16), thus we set the hardware DAC
297 * using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
298 *
299 * For visuals that require color info from the pseudo_palette, we also construct
300 * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
301 * will be set.
302 *
303 * Case 2 - linux_logo_vga16:
304 * The number of colors just matches the console colors, thus there is no need
305 * to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
306 * each byte contains color information for two pixels (upper and lower nibble).
307 * To be consistent with fb_imageblit() usage, we therefore separate the two
308 * nibbles into separate bytes. The "depth" flag will be set to 4.
309 *
310 * Case 3 - linux_logo_mono:
311 * This is similar with Case 2. Each byte contains information for 8 pixels.
312 * We isolate each bit and expand each into a byte. The "depth" flag will
313 * be set to 1.
314 */
315 static struct logo_data {
316 int depth;
317 int needs_directpalette;
318 int needs_truepalette;
319 int needs_cmapreset;
320 const struct linux_logo *logo;
321 } fb_logo __read_mostly;
322
323 static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
324 {
325 u32 size = width * height, i;
326
327 out += size - 1;
328
329 for (i = size; i--; )
330 *out-- = *in++;
331 }
332
333 static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
334 {
335 int i, j, h = height - 1;
336
337 for (i = 0; i < height; i++)
338 for (j = 0; j < width; j++)
339 out[height * j + h - i] = *in++;
340 }
341
342 static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
343 {
344 int i, j, w = width - 1;
345
346 for (i = 0; i < height; i++)
347 for (j = 0; j < width; j++)
348 out[height * (w - j) + i] = *in++;
349 }
350
351 static void fb_rotate_logo(struct fb_info *info, u8 *dst,
352 struct fb_image *image, int rotate)
353 {
354 u32 tmp;
355
356 if (rotate == FB_ROTATE_UD) {
357 fb_rotate_logo_ud(image->data, dst, image->width,
358 image->height);
359 image->dx = info->var.xres - image->width - image->dx;
360 image->dy = info->var.yres - image->height - image->dy;
361 } else if (rotate == FB_ROTATE_CW) {
362 fb_rotate_logo_cw(image->data, dst, image->width,
363 image->height);
364 tmp = image->width;
365 image->width = image->height;
366 image->height = tmp;
367 tmp = image->dy;
368 image->dy = image->dx;
369 image->dx = info->var.xres - image->width - tmp;
370 } else if (rotate == FB_ROTATE_CCW) {
371 fb_rotate_logo_ccw(image->data, dst, image->width,
372 image->height);
373 tmp = image->width;
374 image->width = image->height;
375 image->height = tmp;
376 tmp = image->dx;
377 image->dx = image->dy;
378 image->dy = info->var.yres - image->height - tmp;
379 }
380
381 image->data = dst;
382 }
383
384 static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
385 int rotate, unsigned int num)
386 {
387 unsigned int x;
388
389 if (rotate == FB_ROTATE_UR) {
390 for (x = 0;
391 x < num && image->dx + image->width <= info->var.xres;
392 x++) {
393 info->fbops->fb_imageblit(info, image);
394 image->dx += image->width + 8;
395 }
396 } else if (rotate == FB_ROTATE_UD) {
397 for (x = 0; x < num && image->dx >= 0; x++) {
398 info->fbops->fb_imageblit(info, image);
399 image->dx -= image->width + 8;
400 }
401 } else if (rotate == FB_ROTATE_CW) {
402 for (x = 0;
403 x < num && image->dy + image->height <= info->var.yres;
404 x++) {
405 info->fbops->fb_imageblit(info, image);
406 image->dy += image->height + 8;
407 }
408 } else if (rotate == FB_ROTATE_CCW) {
409 for (x = 0; x < num && image->dy >= 0; x++) {
410 info->fbops->fb_imageblit(info, image);
411 image->dy -= image->height + 8;
412 }
413 }
414 }
415
416 static int fb_show_logo_line(struct fb_info *info, int rotate,
417 const struct linux_logo *logo, int y,
418 unsigned int n)
419 {
420 u32 *palette = NULL, *saved_pseudo_palette = NULL;
421 unsigned char *logo_new = NULL, *logo_rotate = NULL;
422 struct fb_image image;
423
424 /* Return if the frame buffer is not mapped or suspended */
425 if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
426 info->flags & FBINFO_MODULE)
427 return 0;
428
429 image.depth = 8;
430 image.data = logo->data;
431
432 if (fb_logo.needs_cmapreset)
433 fb_set_logocmap(info, logo);
434
435 if (fb_logo.needs_truepalette ||
436 fb_logo.needs_directpalette) {
437 palette = kmalloc(256 * 4, GFP_KERNEL);
438 if (palette == NULL)
439 return 0;
440
441 if (fb_logo.needs_truepalette)
442 fb_set_logo_truepalette(info, logo, palette);
443 else
444 fb_set_logo_directpalette(info, logo, palette);
445
446 saved_pseudo_palette = info->pseudo_palette;
447 info->pseudo_palette = palette;
448 }
449
450 if (fb_logo.depth <= 4) {
451 logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
452 if (logo_new == NULL) {
453 kfree(palette);
454 if (saved_pseudo_palette)
455 info->pseudo_palette = saved_pseudo_palette;
456 return 0;
457 }
458 image.data = logo_new;
459 fb_set_logo(info, logo, logo_new, fb_logo.depth);
460 }
461
462 image.dx = 0;
463 image.dy = y;
464 image.width = logo->width;
465 image.height = logo->height;
466
467 if (rotate) {
468 logo_rotate = kmalloc(logo->width *
469 logo->height, GFP_KERNEL);
470 if (logo_rotate)
471 fb_rotate_logo(info, logo_rotate, &image, rotate);
472 }
473
474 fb_do_show_logo(info, &image, rotate, n);
475
476 kfree(palette);
477 if (saved_pseudo_palette != NULL)
478 info->pseudo_palette = saved_pseudo_palette;
479 kfree(logo_new);
480 kfree(logo_rotate);
481 return logo->height;
482 }
483
484
485 #ifdef CONFIG_FB_LOGO_EXTRA
486
487 #define FB_LOGO_EX_NUM_MAX 10
488 static struct logo_data_extra {
489 const struct linux_logo *logo;
490 unsigned int n;
491 } fb_logo_ex[FB_LOGO_EX_NUM_MAX];
492 static unsigned int fb_logo_ex_num;
493
494 void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
495 {
496 if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
497 return;
498
499 fb_logo_ex[fb_logo_ex_num].logo = logo;
500 fb_logo_ex[fb_logo_ex_num].n = n;
501 fb_logo_ex_num++;
502 }
503
504 static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
505 unsigned int yres)
506 {
507 unsigned int i;
508
509 /* FIXME: logo_ex supports only truecolor fb. */
510 if (info->fix.visual != FB_VISUAL_TRUECOLOR)
511 fb_logo_ex_num = 0;
512
513 for (i = 0; i < fb_logo_ex_num; i++) {
514 height += fb_logo_ex[i].logo->height;
515 if (height > yres) {
516 height -= fb_logo_ex[i].logo->height;
517 fb_logo_ex_num = i;
518 break;
519 }
520 }
521 return height;
522 }
523
相关阅读 更多 +
排行榜 更多 +