Chinaunix首页 | 论坛 | 博客
  • 博客访问: 32336
  • 博文数量: 12
  • 博客积分: 445
  • 博客等级: 下士
  • 技术积分: 150
  • 用 户 组: 普通用户
  • 注册时间: 2012-10-06 16:49
文章分类

全部博文(12)

文章存档

2012年(12)

我的朋友

分类: 嵌入式

2012-10-21 23:03:17

12、u-boot开机logo的制作

    u-boot中显示开机logo需要LCD驱动的支持,在启动过程中会在屏幕的左上角显示一个logo,默认的是一个小企鹅图片。

    先来添加适合我们开发板的LCD驱动程序,取名smdk2440_lcd.c,然后把这个文件放在drivers/video/目录下,代码如下:

  1. /********************************************************
  2. s3c2410 fb driver for smdk2440
  3. ********************************************************/
  4. #include
  5.  
  6. #if defined(CONFIG_VIDEO_S3C2440)
  7.  
  8. #include
  9. #include "videomodes.h"
  10. #include
  11. #include
  12. /*
  13.  * Export Graphic Device
  14.  */
  15. GraphicDevice smi;
  16.  
  17. #define VIDEO_MEM_SIZE 0x200000

  18. #define MVAL            (0)
  19. #define MVAL_USED         (0)     //0=each frame 1=rate by MVAL
  20. #define INVVDEN            (1)     //0=normal 1=inverted
  21. #define BSWP            (0)     //Byte swap control
  22. #define HWSWP            (1)     //Half word swap control

  23. #define VBPD            (12)
  24. #define VFPD            (4)
  25. #define VSPW            (10)
  26. #define HBPD            (43)
  27. #define HFPD            (8)
  28. #define HSPW            (1)
  29. #define CLKVAL_TFT        (4)

  30. void lcd_enable(void)
  31. {
  32.     struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
  33.     struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd();

  34.     gpio->GPGUP = gpio->GPGUP & ((~(1 << 4)) | (1 << 4));
  35.     gpio->GPGCON = gpio->GPGCON & ((~( 3 << 8)) | ( 3 << 8));
  36.     gpio->GPGDAT = gpio->GPGDAT | (1 << 4 );

  37.     lcd->LCDCON5 = lcd->LCDCON5 & ((~( 1 << 3)) | (1 << 3));  //PWREN
  38.     lcd->LCDCON5 = lcd->LCDCON5 & ((~( 1 << 5)) | (0 << 5));//INVPWREN

  39.     lcd->LCDCON1 |= 1;
  40.     
  41.     gpio->GPBUP = gpio->GPBUP & ((~(1 << 1)) | (1 << 1));
  42.     gpio->GPBCON = gpio->GPBCON & ((~( 3 << 2)) | ( 3 << 2));
  43.     gpio->GPBDAT = gpio->GPBDAT | (1 << 1 );
  44. }
  45.  
  46. /*******************************************************************************
  47.  *
  48.  * Init video chip with common Linux graphic modes (lilo)
  49.  */
  50. void *video_hw_init (void)
  51. {
  52.     struct s3c24x0_lcd * const lcd = s3c24x0_get_base_lcd();
  53.     GraphicDevice *pGD = (GraphicDevice *)&smi;
  54.     int videomode;
  55.     int bppmode;
  56.     unsigned long t1, hsynch, vsynch;
  57.     char *penv;
  58.     int tmp, i, bits_per_pixel;
  59.     struct ctfb_res_modes *res_mode;
  60.     struct ctfb_res_modes var_mode;

  61.     tmp = 0;
  62.  
  63.     videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
  64.     /* get video mode via environment */
  65.     if ((penv = getenv ("videomode")) != NULL) {
  66.          /* deceide if it is a string */
  67.         if (penv[0] <= '9') {
  68.             videomode = (int) simple_strtoul (penv, NULL, 16);
  69.             tmp = 1;
  70.         }
  71.     }
  72.     else
  73.     {
  74.         tmp = 1;
  75.     }
  76.     if (tmp) {
  77.         /* parameter are vesa modes */
  78.         /* search params */
  79.         for (i = 0; i < VESA_MODES_COUNT; i++) {
  80.             if (vesa_modes[i].vesanr == videomode)
  81.             break;
  82.         }
  83.          if (i == VESA_MODES_COUNT) {
  84.             printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
  85.             i = 0;
  86.         }
  87.         res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].resindex];
  88.         bits_per_pixel = vesa_modes[i].bits_per_pixel;
  89.     } 
  90.     else
  91.     {
  92.         res_mode = (struct ctfb_res_modes *) &var_mode;
  93.         bits_per_pixel = video_get_params (res_mode, penv);
  94.     }
  95.  
  96.     /* calculate hsynch and vsynch freq (info only) */
  97.     t1 = (res_mode->left_margin + res_mode->xres + res_mode->right_margin + res_mode->hsync_len) / 8;
  98.     t1 *= 8;
  99.     t1 *= res_mode->pixclock;
  100.     t1 /= 1000;
  101.     hsynch = 1000000000L / t1;
  102.     t1 *= (res_mode->upper_margin + res_mode->yres + res_mode->lower_margin + res_mode->vsync_len);
  103.     t1 /= 1000;
  104.     vsynch = 1000000000L / t1;

  105.     /* fill in Graphic device struct */
  106.     sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres, res_mode->yres, bits_per_pixel, (hsynch / 1000), (vsynch / 1000));

  107.     pGD->winSizeX = res_mode->xres;
  108.     pGD->winSizeY = res_mode->yres;
  109.     pGD->plnSizeX = res_mode->xres;
  110.     pGD->plnSizeY = res_mode->yres;
  111.      
  112.     switch (bits_per_pixel)
  113.     {
  114.         case 8:
  115.             pGD->gdfBytesPP = 1;
  116.             pGD->gdfIndex = GDF__8BIT_INDEX;
  117.             bppmode = 11;
  118.          break;
  119.         case 16:
  120.             pGD->gdfBytesPP = 2;
  121.             pGD->gdfIndex = GDF_16BIT_565RGB;
  122.             bppmode = 12;
  123.          break;
  124.         case 24:
  125.          pGD->gdfBytesPP = 3;
  126.          pGD->gdfIndex = GDF_24BIT_888RGB;
  127.             bppmode = 13;
  128.          break;
  129.     }

  130.     pGD->frameAdrs = LCD_VIDEO_ADDR;
  131.     pGD->memSize = VIDEO_MEM_SIZE;

  132.     lcd->LCDCON1 = (CLKVAL_TFT << 8) | (MVAL_USED << 7) | (3 << 5) | (bppmode << 1) | 0;
  133.     lcd->LCDCON2 = (VBPD << 24) | (pGD->winSizeY-1 << 14) | (VFPD << 6) | (VSPW);
  134.     lcd->LCDCON3 = (HBPD << 19) | (pGD->winSizeX-1 << 8) | (HFPD);
  135.     lcd->LCDCON4 = (MVAL << 8) | (HSPW);
  136.     lcd->LCDCON5 = (1 << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 7) | (0 << 6) | (1 << 3) | (BSWP << 1) | (HWSWP);

  137.     lcd->LCDINTMSK |= (3);
  138.     lcd->LPCSEL &= (~7);
  139.     lcd->TPAL = 0x0;

  140.     writel((pGD->frameAdrs >> 1), &lcd->LCDSADDR1); 
  141.  
  142.     /* This marks the end of the frame buffer. */
  143.     writel((((readl(&lcd->LCDSADDR1))&0x1fffff) + (pGD->winSizeX+0) * pGD->winSizeY), &lcd->LCDSADDR2); 
  144.     writel((pGD->winSizeX & 0x7ff), &lcd->LCDSADDR3); 
  145.  
  146.     /* Clear video memory */
  147.     memset((void *)pGD->frameAdrs, 0, pGD->memSize);

  148.     lcd_enable();
  149.  
  150.     return ((void*)&smi);
  151. }
  152.  
  153. void video_set_lut (unsigned int index, /* color number */
  154.                 unsigned char r, /* red */
  155.                 unsigned char g, /* green */
  156.                 unsigned char b /* blue */
  157.         )
  158.  {
  159.  }
  160.  
  161.  #endif 
   
    在videomodes.c和videomodes.h文件中增加或者修改LCD程序smdk2440_lcd.c需要的宏CONFIG_SYS_DEFAULT_VIDEO_MODE,宏RES_MODE_480x272,宏RES_MODES_COUNT,宏VESA_MODES_COUNTvesa_modes[]数组,res_mode_init[]数组。
    
    在videomodes.c中增加的代码如下:
  1. const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = {
  2.     {0x301, RES_MODE_640x480, 8},
  3.     {0x310, RES_MODE_640x480, 15},
  4.     {0x311, RES_MODE_640x480, 16},
  5.     {0x312, RES_MODE_640x480, 24},
  6.     {0x303, RES_MODE_800x600, 8},
  7.     {0x313, RES_MODE_800x600, 15},
  8.     {0x314, RES_MODE_800x600, 16},
  9.     {0x315, RES_MODE_800x600, 24},
  10.     {0x305, RES_MODE_1024x768, 8},
  11.     {0x316, RES_MODE_1024x768, 15},
  12.     {0x317, RES_MODE_1024x768, 16},
  13.     {0x318, RES_MODE_1024x768, 24},
  14.     {0x161, RES_MODE_1152x864, 8},
  15.     {0x162, RES_MODE_1152x864, 15},
  16.     {0x163, RES_MODE_1152x864, 16},
  17.     {0x307, RES_MODE_1280x1024, 8},
  18.     {0x319, RES_MODE_1280x1024, 15},
  19.     {0x31A, RES_MODE_1280x1024, 16},
  20.     {0x31B, RES_MODE_1280x1024, 24},
  21.     {0x211, RES_MODE_480x272, 16}, 
  22. };

  23. const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = {
  24.     /* x     y pixclk le    ri up    lo hs vs s vmode */
  25.     {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED},
  26.     {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED},
  27.     {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, FB_VMODE_NONINTERLACED},
  28.     {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, FB_VMODE_NONINTERLACED},
  29.     {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, FB_VMODE_NONINTERLACED},
  30.     {1280, 1024, 9090, 200, 48, 26, 1, 184, 3, 0, FB_VMODE_NONINTERLACED},
  31.     {480, 272, 40000, 8, 43, 2, 4, 12, 10, 0, FB_VMODE_NONINTERLACED},
  32. };

    在videomodes.h中修改和增加的代码如下:
  1. #ifndef CONFIG_SYS_DEFAULT_VIDEO_MODE
  2. #define CONFIG_SYS_DEFAULT_VIDEO_MODE    0x211 
  3. #endif

 #define RES_MODE_640x480 0
 #define RES_MODE_800x600 1
 #define RES_MODE_1024x768 2
 #define RES_MODE_960_720 3
 #define RES_MODE_1152x864 4
 #define RES_MODE_1280x1024 5
 #define RES_MODE_480x272 6  
 #define RES_MODES_COUNT  

#define VESA_MODES_COUNT        20    

    修改drivers/video/目录下的Makefile文件,增加smdk2440_lcd.c的编译选项,修改的代码如下:
  1. COBJS-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o
  2. COBJS-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o
  3. COBJS-y += videomodes.o
  4. COBJS-y += smdk2440_lcd.o 
    
    显示LOGO的函数调用流程如下:
    在lib_arm/board.c中的start_armboot函数中调用common/stdio.c中的stdio_init
,如果定义了CONFIG_VIDEO或者CONFIG_CFB_CONSOLE,调用drivers/video/cfb_console.c中的drv_video_init函数,该函数中的video_init函数先调用smdk2440_lcd.c中的video_hw_init函数,接着video_logo调用logo_plot显示logo。

    现在在smdk2440.h文件中定义和LCD LOGO相关的宏,增加的代码如下:
  1. #define CONFIG_CMD_BMP 
  2. #define CONFIG_CFB_CONSOLE
  3. #define LCD_VIDEO_ADDR 0x33d00000
  4. #define CONFIG_VIDEO 
  5. #define CONFIG_VIDEO_S3C2440  //定义了这个宏就可以编译smdk2440_lcd.c
  6. #define CONFIG_VIDEO_LOGO

  7. #define VIDEO_KBD_INIT_FCT 0 
  8. #define VIDEO_TSTC_FCT serial_tstc 
  9. #define VIDEO_GETC_FCT serial_getc

  10. #define CONFIG_SYS_CONSOLE_IS_IN_ENV
  11. #define VIDEO_FB_16BPP_WORD_SWAP //控制字体的显示模式,不然字体显示模糊

    重新编译u-boot,下载到NandFlash中运行,启动的过程中就会在屏幕左上角显示logo,是一个小企鹅图片。

显示自定义的图片logo
    如果又定义了宏VIDEO_BMP_LOGO编译时会执行tools目录下的bmp_logo程序,读取"tools/logos/denx.bmp"文件,在include下生成bmp_logo.h文件,该文件的内容如下:
  1. #define BMP_LOGO_WIDTH        160
  2. #define BMP_LOGO_HEIGHT        96
  3. #define BMP_LOGO_COLORS        31
  4. #define BMP_LOGO_OFFSET        16

  5. unsigned short bmp_logo_palette[] = {
  6. ....................................
  7. }
 unsigned short bmp_logo_bitmap[] = {
  1. ....................................
  2. }
   显示logo函数就会调用这个数组中的数据,显示到屏上。在cfb_console.c中定义了LOGO的属性,代码如下:
  1. #ifdef    CONFIG_VIDEO_LOGO
  2. #ifdef    CONFIG_VIDEO_BMP_LOGO
  3. #include
  4. #define VIDEO_LOGO_WIDTH    BMP_LOGO_WIDTH
  5. #define VIDEO_LOGO_HEIGHT    BMP_LOGO_HEIGHT
  6. #define VIDEO_LOGO_LUT_OFFSET    BMP_LOGO_OFFSET
  7. #define VIDEO_LOGO_COLORS    BMP_LOGO_COLORS

    三星平台默认使用denx.bmp图片(在tools/logos/目录下)作为自定义的BMP logo,把自己的logo图片改成这个文件名,再编译就行了。这个bmp文件是有要求的,位深度必须为8位,大小也有限制(全屏图片肯定是不行的,读取文件的后半部数据都是0)。

   在smdk2440.h中增加宏VIDEO_BMP_LOGO,修改的代码如下:
  1. #define CONFIG_VIDEO_S3C2440 
  2. #define CONFIG_VIDEO_LOGO
  3. #define CONFIG_VIDEO_BMP_LOGO
   
   重新编译u-boot,下载到NandFlash中运行,启动的过程中就会在屏幕左上角显示自定义的logo。
阅读(1247) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~