zoukankan      html  css  js  c++  java
  • 【转载】帧缓冲驱动程序分析及其在BSP上的添加

    原文地址:(四)帧缓冲驱动程序分析及其在BSP上的添加 作者:gfvvz

    一、BSP修改及其分析
     
    1. BSP中直接配置的四个寄存器
    S3C6410数据手册的第14.5部分是显示控制器的编程模型部分,图1是开始部分截图。如第一行所说,这些寄存器是配置显示控制器用的。所以,所有的寄存器设置都围绕这些寄存器进行。
          其中前面四个寄存器SPCONMOFPCONVIDCON0VIDCON0,直接在BSP中进行配置
    图 1
     
    A. SPCONMOFPCON寄存器:如下代码中,配置SPCON和MOFPCON寄存器,使得显示控制器工作于:“RGB I/F类型”、“normal模式”。

    点击(此处)折叠或打开

    1. /* 修改内容1:LCD接口类型及模式设置
    2.  * BSP中位于 static void __init jason6410_map_io(void){} 函数内。
    3.  */
    4.     /* set the LCD type */
    5.     tmp = __raw_readl(S3C64XX_SPCON);//读取当前SPCON寄存器值
    6.     tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;//清零LCD_SEL[1:0]
    7.     tmp |= S3C64XX_SPCON_LCD_SEL_RGB;//置位最后一位,LCD_SEL[1:0] = 01
    8.     __raw_writel(tmp, S3C64XX_SPCON);//写入LCD_SEL[1:0] = 01的值到SPCON寄存器,“RGB I/F style”
    9.     /* remove the lcd bypass */
    10.     tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);//读取当前MOFPCON寄存器值
    11.     tmp &= ~MIFPCON_LCD_BYPASS;//清零SEL_BYPASS[3]
    12.     __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);//写入SEL_BYPASS[3]已清零的值到MOFPCON寄存器,"normal mode"

    点击(此处)折叠或打开

    1. /* 使用到的宏定义 */ 
    2. #define S3C64XX_SPCON_LCD_SEL_MASK      (0x3 << 0)
    3. #define S3C64XX_SPCON_LCD_SEL_RGB       (0x1 << 0)
    4.  
    5. #define MIFPCON_LCD_BYPASS(1 << 3)
    B、VIDCON0VIDCON1寄存器:如下代码中,配置VIDCON0和VIDCON1寄存器。
    a.配置VIDCON0寄存器: 输出格式为“RGB I/F”,显示模式为“RGB Parallel format (RGB)”;
    b.配置VIDCON1寄存器:配置行同步信号HSYNC与帧同步信号VSYNC极性取反。因为S3C6410的LCD RGB接口的时序中,HSYNC和VSYNC与一般TFT屏极性相反,故需要配置极性取反。如下图5为S3C6410的LCD RGB接口的时序,下图6为一般TFT屏工作时序。

    点击(此处)折叠或打开

    1. /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
    2. static struct s3c_fb_platdata jason6410_lcd_pdata __initdata = {
    3.     .setup_gpio = s3c64xx_fb_gpio_setup_24bpp,//配置数据信号线GPIO
    4.     .win[0]     = &jason6410_fb_win0,//LCD屏参数
    5.     .vidcon0    = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,//配置VIDCON0寄存器
    6.     .vidcon1    = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,//配置VIDCON1寄存器
    7. };
    8.  
    9. //配置LCD数据信号线GPIO
    10. extern void s3c64xx_fb_gpio_setup_24bpp(void)
    11. {
    12. s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2));//GPI
    13. s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2));//GPJ
    14. }

    点击(此处)折叠或打开

    1. /* 使用到的宏定义 */   
    2.  
    3. #define VIDCON0_VIDOUT_RGB            (0x0 << 26)  //见下图2
    4. #define VIDCON0_PNRMODE_RGB(0x0 << 17)//见下图3
    5. #define VIDCON1_INV_HSYNC(1 << 6)//见下图4
    6. #define VIDCON1_INV_VSYNC(1 << 5)//见下图4
    图 2
    图 3
    图4
    图 5
    图 6
     
    2、帧缓冲设备参数计算及设置
     上面讲到的四个寄存器,对于同一处理器下不同厂家、不同尺寸的TFT屏基本上都是一样的。但是,对于下面几个定时和硬件参数:行切换、帧切换、水平同步长度、垂直同步长度、X像素、Y像素。不同厂家的不同尺寸的TFT屏之间,往往是不同的,或者说是需要重新计算和修改的。
    下面先解释上面图5中的几个参数:
    A. VBPD(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数,对应驱动中的upper_margin
    B. VFBD(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数,对应驱动中的lower_margin
    C. VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算,对应驱动中的vsync_len
    D. HBPD(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数,对应驱动中的left_margin
    E. HFPD(horizontal front porth):表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数,对应驱动中的right_margin
    F. HSPW(horizontal sync pulse width):表示水平同步信号的宽度,用VCLK计算,对应驱动中的hsync_len
    这几个参数都是基于行数或者VCLK个数,所以其数据必须是严格的,不能有偏差,一旦有一个数不对,整个屏幕都不能显示。

    点击(此处)折叠或打开

    1. static struct s3c_fb_pd_win jason6410_fb_win0 = {
    2.     /* this is to ensure we use win0 */
    3.     .win_mode    = {
    4. #if 0
    5.         .pixclock    = 115440,//pixel clock in ps (pico seconds)
    6. #endif
    7.         .left_margin    = 0x03,//time from sync to picture
    8.         .right_margin   = 0x02,//time from picture to sync
    9.         .upper_margin   = 0x01,//time from sync to picture
    10.         .lower_margin   = 0x01,//time from picture to sync
    11.         .hsync_len   = 0x28,//length of horizontal sync
    12.         .vsync_len    = 0x01,//length of vertical sync
    13.         .xres        = 480,
    14.         .yres        = 272,
    15.     },
    16.     .max_bpp    = 32,
    17.     .default_bpp    = 16,
    18. };
    19.  
    20.  附:下图摘自内核里的Documentation/fb/framebuffer.txt
    21.  
    22. Video Mode Timings
     +----------+---------------------------------------------+----------+-------+
      |          |                ↑                            |          |       |
      |          |                |upper_margin                |          |       |
      |          |                ↓                            |          |       |
      +----------###############################################----------+-------+
      |          #                ↑                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |   left   #                |                            #  right   | hsync |
      |  margin  #                |       xres                 #  margin  |  len  |
      |<-------->#<---------------+--------------------------->#<-------->|<----->|
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |yres                        #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                |                            #          |       |
      |          #                ↓                            #          |       |
      +----------###############################################----------+-------+
      |          |                ↑                            |          |       |
      |          |                |lower_margin                |          |       |
      |          |                ↓                            |          |       |
      +----------+---------------------------------------------+----------+-------+
      |          |                ↑                            |          |       |
      |          |                |vsync_len                   |          |       |
      |          |                ↓                            |          |       |
      +----------+---------------------------------------------+----------+-------+
     
    3、BSP部分注册帧缓冲平台设备
    如下代码完成s3c_device_fb平台设备结构体的设置。

    点击(此处)折叠或打开

    1. static struct s3c_fb_pd_win jason6410_fb_win0 = {
    2.     /* this is to ensure we use win0 */
    3.     .win_mode    = {
    4. #if 0
    5.         .pixclock    = 115440,
    6. #endif
    7.         .left_margin    = 0x03,
    8.         .right_margin   = 0x02,
    9.         .upper_margin   = 0x01,
    10.         .lower_margin   = 0x01,
    11.         .hsync_len    = 0x28,
    12.         .vsync_len    = 0x01,
    13.         .xres        = 480,
    14.         .yres        = 272,
    15.     },
    16.     .max_bpp    = 32,
    17.     .default_bpp    = 16,
    18. };
    19. /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
    20. static struct s3c_fb_platdata jason6410_lcd_pdata __initdata = {
    21.     .setup_gpio    = s3c64xx_fb_gpio_setup_24bpp,
    22.     .win[0]        = &jason6410_fb_win0,
    23.     .vidcon0    = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
    24.     .vidcon1    = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
    25. };
    26.  
    27. //static void __init jason6410_machine_init(void)函数中:
    28. s3c_fb_set_platdata(&jason6410_lcd_pdata);
    参看arch/arm/plat-samsung/devs.c中FB部分,如下代码。

    点击(此处)折叠或打开

    1. /* FB */
    2. #ifdef CONFIG_S3C_DEV_FB
    3. static struct resource s3c_fb_resource[] = {
    4.     [0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
    5.     [1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
    6.     [2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
    7.     [3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
    8. };
    9. struct platform_device s3c_device_fb = {
    10.     .name        = "s3c-fb",
    11.     .id        = -1,
    12.     .num_resources    = ARRAY_SIZE(s3c_fb_resource),
    13.     .resource    = s3c_fb_resource,
    14.     .dev        = {
    15.         .dma_mask        = &samsung_device_dma_mask,
    16.         .coherent_dma_mask    = DMA_BIT_MASK(32),
    17.     },
    18. };
    19. void __init s3c_fb_set_platdata(struct s3c_fb_platdata *pd)
    20. {
    21.     s3c_set_platdata(pd, sizeof(struct s3c_fb_platdata),
    22.              &s3c_device_fb);
    23. }
    24. #endif /* CONFIG_S3C_DEV_FB */
    最终,设置完s3c_device_fb平台设备结构体,结构体之间的关系如下:

    点击(此处)折叠或打开

    1. //1. s3c_device_fb平台设备结构体
    2. struct platform_device s3c_device_fb = {
    3.     .name        = "s3c-fb",
    4.     .id        = -1,
    5.     .num_resources    = ARRAY_SIZE(s3c_fb_resource),
    6.     .resource    = s3c_fb_resource,
    7.     .dev        = {
    8.         .dma_mask        = &samsung_device_dma_mask,
    9.         .coherent_dma_mask    = DMA_BIT_MASK(32),
    10.     },
    11. };
    12.  
    13. //2. s3c_device_fb平台设备结构体中的resource结构体
    14. static struct resource s3c_fb_resource[] = {
    15. [0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
    16. [1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
    17. [2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
    18. [3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
    19. };
    20.  
    21. //3. s3c_device_fb平台设备结构体中的dev结构体里私有数据指针所指向的平台私有数据
    22. static struct s3c_fb_platdata jason6410_lcd_pdata __initdata = {
    23. .setup_gpio= s3c64xx_fb_gpio_setup_24bpp,
    24. .win[0]= &jason6410_fb_win0,
    25. .vidcon0= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
    26. .vidcon1= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
    27. };
    28.  
    29. //4. 平台私有数据jason6410_lcd_pdata结构体里的window_settings结构体
    30. static struct s3c_fb_pd_win jason6410_fb_win0 = {
    31. /* this is to ensure we use win0 */
    32. .win_mode= {
    33. #if 0
    34. .pixclock= 115440,
    35. #endif
    36. .left_margin= 0x03,
    37. .right_margin= 0x02,
    38. .upper_margin= 0x01,
    39. .lower_margin= 0x01,
    40. .hsync_len= 0x28,
    41. .vsync_len= 0x01,
    42. .xres= 480,
    43. .yres= 272,
    44. },
    45. .max_bpp= 32,
    46. .default_bpp= 16,
    47. };
    48.  
    49. /* 
    50.  * 实际上,相当于有如下个红色标注的结构体
    51.  * 1. 在jason6410_machine_init函数里的platform_add_devices函数注册s3c_device_fb平台设备结构体;
    52.  * 2. 通过私有数据指针找到jason6410_lcd_pdata结构体;
    53.  * 3. 通过s3c_fb_pd_win结构体指针,找到 jason6410_fb_win0结构体;
    54.  */
    55. struct platform_device s3c_device_fb = {
    56. .name= "s3c-fb",
    57. .id= -1,
    58. .num_resources= ARRAY_SIZE(s3c_fb_resource),
    59. .resource= {
    60. [0] = DEFINE_RES_MEM(S3C_PA_FB, SZ_16K),
    61. [1] = DEFINE_RES_IRQ(IRQ_LCD_VSYNC),
    62. [2] = DEFINE_RES_IRQ(IRQ_LCD_FIFO),
    63. [3] = DEFINE_RES_IRQ(IRQ_LCD_SYSTEM),
    64. }
    65. .dev= {
    66. .platform_data= &jason6410_lcd_pdata,
    67. .dma_mask= &samsung_device_dma_mask,
    68. .coherent_dma_mask= DMA_BIT_MASK(32),
    69. },
    70. };
    71.  
    72. static struct s3c_fb_platdata jason6410_lcd_pdata __initdata = {
    73. .setup_gpio= s3c64xx_fb_gpio_setup_24bpp,
    74. .win[0]= &jason6410_fb_win0,
    75. .vidcon0= VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
    76. .vidcon1= VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
    77. };
    78.  
    79. static struct s3c_fb_pd_win jason6410_fb_win0 = {
    80. /* this is to ensure we use win0 */
    81. .win_mode= {
    82. #if 0
    83. .pixclock= 115440,
    84. #endif
    85. .left_margin= 0x03,
    86. .right_margin= 0x02,
    87. .upper_margin= 0x01,
    88. .lower_margin= 0x01,
    89. .hsync_len= 0x28,
    90. .vsync_len= 0x01,
    91. .xres= 480,
    92. .yres= 272,
    93. },
    94. .max_bpp= 32,
    95. .default_bpp= 16,
    96. };
     

    点击(此处)折叠或打开

    1. /* linux/arch/arm/mach-s3c64xx/mach-jason6410.c
    2.  *
    3.  * Copyright 2012 Jason Lu <gfvvz@yahoo.com.cn>
    4.  *     http://jason2012.blog.chinaunix.net
    5.  *
    6.  * This program is free software; you can redistribute it and/or modify
    7.  * it under the terms of the GNU General Public License version 2 as
    8.  * published by the Free Software Foundation.
    9.  *
    10. */
    11. #include <linux/init.h>
    12. #include <linux/interrupt.h>
    13. #include <linux/fb.h>
    14. #include <linux/gpio.h>
    15. #include <linux/kernel.h>
    16. #include <linux/list.h>
    17. #include <linux/dm9000.h>
    18. #include <linux/mtd/mtd.h>
    19. #include <linux/mtd/partitions.h>
    20. #include <linux/serial_core.h>
    21. #include <linux/types.h>
    22. #include <asm/mach-types.h>
    23. #include <asm/mach/arch.h>
    24. #include <asm/mach/map.h>
    25. #include <mach/map.h>
    26. #include <mach/regs-gpio.h>
    27. #include <mach/regs-modem.h>
    28. #include <mach/regs-srom.h>
    29. #include <plat/s3c6410.h>
    30. #include <plat/adc.h>
    31. #include <plat/cpu.h>
    32. #include <plat/devs.h>
    33. #include <plat/fb.h>
    34. #include <plat/nand.h>
    35. #include <plat/regs-serial.h>
    36. #include <plat/ts.h>
    37. #include <plat/regs-fb-v4.h>
    38. #include <plat/iic.h>
    39. #include <video/platform_lcd.h>
    40. #define UCON S3C2410_UCON_DEFAULT
    41. #define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
    42. #define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
    43. static struct s3c2410_uartcfg jason6410_uartcfgs[] __initdata = {
    44.     [0] = {
    45.         .hwport= 0,
    46.         .flags    = 0,
    47.         .ucon    = UCON,
    48.         .ulcon    = ULCON,
    49.         .ufcon    = UFCON,
    50.     },
    51.     [1] = {
    52.         .hwport    = 1,
    53.         .flags    = 0,
    54.         .ucon    = UCON,
    55.         .ulcon    = ULCON,
    56.         .ufcon    = UFCON,
    57.     },
    58.     [2] = {
    59.         .hwport    = 2,
    60.         .flags    = 0,
    61.         .ucon    = UCON,
    62.         .ulcon   = ULCON,
    63.         .ufcon    = UFCON,
    64.     },
    65.     [3] = {
    66.         .hwport    = 3,
    67.         .flags    = 0,
    68.         .ucon    = UCON,
    69.         .ulcon    = ULCON,
    70.         .ufcon    = UFCON,
    71.     },
    72. };
    73. /* Framebuffer. */
    74.  
    75. static struct s3c_fb_pd_win jason6410_fb_win0 = {
    76.     /* this is to ensure we use win0 */
    77.     .win_mode    = {
    78. #if 0
    79.         .pixclock    = 115440,
    80. #endif
    81.         .left_margin    = 0x03,
    82.         .right_margin= 0x02,
    83.         .upper_margin= 0x01,
    84.         .lower_margin= 0x01,
    85.         .hsync_len    = 0x28,
    86.         .vsync_len   = 0x01,
    87.         .xres        = 480,
    88.         .yres        = 272,
    89.     },
    90.     .max_bpp    = 32,
    91.     .default_bpp    = 16,
    92. };
    93.  
    94. /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
    95. static struct s3c_fb_platdata jason6410_lcd_pdata __initdata = {
    96.     .setup_gpio    = s3c64xx_fb_gpio_setup_24bpp,
    97.     .win[0]        = &jason6410_fb_win0,
    98.     .vidcon0    = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
    99.     .vidcon1    = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
    100. };
    101. /* Nand flash */
    102. static struct mtd_partition jason6410_nand_part[] = {
    103.     {
    104.         .name        = "u-boot-2011.06",
    105.         .offset        = 0,
    106.         .size        = (4 * 128 *SZ_1K),
    107.         .mask_flags    = MTD_CAP_NANDFLASH,
    108.     },
    109.     {
    110.         .name        = "Linux Kernel 3.2.8",
    111.         .offset        = MTDPART_OFS_APPEND,
    112.         .size        = (5*SZ_1M) ,
    113.         .mask_flags    = MTD_CAP_NANDFLASH,
    114.     },
    115.     {
    116.         .name        = "UBI File System",
    117.         .offset        = MTDPART_OFS_APPEND,
    118.         .size        = MTDPART_SIZ_FULL,
    119.     }
    120. };
    121. static struct s3c2410_nand_set jason6410_nand_sets[] = {
    122.     [0] = {
    123.         .name        = "nand",
    124.         .nr_chips    = 1,
    125.         .nr_partitions = ARRAY_SIZE(jason6410_nand_part),
    126.         .partitions    = jason6410_nand_part,
    127.     },
    128. };
    129. static struct s3c2410_platform_nand jason6410_nand_info = {
    130.     .tacls= 25,
    131.     .twrph0 = 55,
    132.     .twrph1  = 40,
    133.     .nr_sets    = ARRAY_SIZE(jason6410_nand_sets),
    134.     .sets     = jason6410_nand_sets,
    135. };
    136. static struct platform_device *jason6410_devices[] __initdata = {
    137.     &s3c_device_nand,
    138.     &s3c_device_i2c0,
    139.     &s3c_device_fb,
    140. };
    141. static struct i2c_board_info i2c_devs0[] __initdata = {
    142.     { I2C_BOARD_INFO("24c08", 0x50), },
    143. };
    144. static struct i2c_board_info i2c_devs1[] __initdata = {
    145.     /* Add your i2c device here */
    146. };
    147. static void __init jason6410_map_io(void)
    148. {
    149.     u32 tmp;
    150.     s3c64xx_init_io(NULL, 0);
    151.     s3c24xx_init_clocks(12000000);
    152.     s3c24xx_init_uarts(jason6410_uartcfgs, ARRAY_SIZE(jason6410_uartcfgs));
    153.     /* set the LCD type */
    154.     tmp = __raw_readl(S3C64XX_SPCON);
    155.     tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
    156.     tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
    157.     __raw_writel(tmp, S3C64XX_SPCON);
    158.  
    159.     /* remove the lcd bypass */
    160.     tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
    161.     tmp &= ~MIFPCON_LCD_BYPASS;
    162.     __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
    163. }
    164. static void __init jason6410_machine_init(void)
    165. {
    166.     s3c_device_nand.name = "s3c6410-nand";
    167.     s3c_nand_set_platdata(&jason6410_nand_info);
    168.     s3c_i2c0_set_platdata(NULL);
    169.     s3c_fb_set_platdata(&jason6410_lcd_pdata);
    170.     if (ARRAY_SIZE(i2c_devs0)) {
    171.         i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
    172.     }
    173.     if (ARRAY_SIZE(i2c_devs1)) {
    174.         i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
    175.     }
    176.     platform_add_devices(jason6410_devices, ARRAY_SIZE(jason6410_devices));
    177. }
    178. MACHINE_START(JASON6410, "JASON6410")
    179.     /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
    180.     .atag_offset    = 0x100,
    181.     .init_irq= s3c6410_init_irq,
    182.     .map_io        = jason6410_map_io,
    183.     .init_machine    = jason6410_machine_init,
    184.     .timer        = &s3c24xx_timer,
    185. MACHINE_END
    4、帧缓冲平台驱动
     
    4.1 s3c_fb_driver平台驱动结构体及其注册
    平台设备与平台驱动匹配的函数如下,先尝试OF类型的匹配,如果匹配不成功,尝试驱动的id_table里是否有与设备名匹配的id,如果还是不能匹配,就回到基于驱动名和设备名的匹配。匹配成功返回1,失败返回0。
    在这里,设备驱动结构体未定义of_match_table,故第一次匹配是不成功的。然后,平台驱动结构体里定义了id_table,且有与平台设备名相同的平台设备ID “s3c-fb”,因此在此匹配,并且把平台设备结构体的id_entry赋值为匹配的ID项。

    点击(此处)折叠或打开

    1. //平台设备设备与驱动匹配函数 
    2. static int platform_match(struct device *dev, struct device_driver *drv)
    3. {
    4.     struct platform_device *pdev = to_platform_device(dev);
    5.     struct platform_driver *pdrv = to_platform_driver(drv);
    6.     /* Attempt an OF style match first */
    7.     if (of_driver_match_device(dev, drv))
    8.         return 1;
    9.     /* Then try to match against the id table */
    10.     if (pdrv->id_table)
    11.         return platform_match_id(pdrv->id_table, pdev) != NULL;
    12.     /* fall-back to driver name match */
    13.     return (strcmp(pdev->name, drv->name) == 0);
    14. }
    15.  
    16. //platform_match_id函数
    17. static const struct platform_device_id *platform_match_id(
    18. const struct platform_device_id *id,
    19. struct platform_device *pdev)
    20. {
    21. while (id->name[0]) {
    22. if (strcmp(pdev->name, id->name) == 0) {
    23. pdev->id_entry = id;
    24. return id;
    25. }
    26. id++;
    27. }
    28. return NULL;
    29. }

    点击(此处)折叠或打开

    1. //@driver/video/s3c-fb.c 
    2.  
    3. //s3c_fb_driver平台驱动结构体
    4. static struct platform_driver s3c_fb_driver = {
    5.     .probe       = s3c_fb_probe,
    6.     .remove      = __devexit_p(s3c_fb_remove),
    7.     .id_table    = s3c_fb_driver_ids,
    8.     .driver      = {
    9.         .name    = "s3c-fb",
    10.         .owner= THIS_MODULE,
    11.         .pm    = &s3cfb_pm_ops,
    12.     },
    13. };
    14.  
    15. //s3c_fb_driver平台驱动结构体注册
    16. static int __init s3c_fb_init(void)
    17. {
    18.     return platform_driver_register(&s3c_fb_driver);
    19. }
    20.   
    21. //s3c_fb_driver平台驱动结构体id_table
    22. static struct platform_device_id s3c_fb_driver_ids[] = {
    23. {
    24. .name= "s3c-fb",//匹配平台设备名的名字
    25. .driver_data= (unsigned long)&s3c_fb_data_64xx,
    26. }, {
    27. .name= "s5pc100-fb",
    28. .driver_data= (unsigned long)&s3c_fb_data_s5pc100,
    29. }, {
    30. .name= "s5pv210-fb",
    31. .driver_data= (unsigned long)&s3c_fb_data_s5pv210,
    32. }, {
    33. .name= "exynos4-fb",
    34. .driver_data= (unsigned long)&s3c_fb_data_exynos4,
    35. }, {
    36. .name= "s3c2443-fb",
    37. .driver_data= (unsigned long)&s3c_fb_data_s3c2443,
    38. }, {
    39. .name= "s5p64x0-fb",
    40. .driver_data= (unsigned long)&s3c_fb_data_s5p64x0,
    41. },
    42. {},
    43. };
    44.   
    45. //平台设备ID结构体中的驱动数据
    46. static struct s3c_fb_driverdata s3c_fb_data_64xx = {
    47. .variant = {
    48. .nr_windows= 5,
    49. .vidtcon= VIDTCON0,
    50. .wincon= WINCON(0),
    51. .winmap= WINxMAP(0),
    52. .keycon= WKEYCON,
    53. .osd= VIDOSD_BASE,
    54. .osd_stride= 16,
    55. .buf_start= VIDW_BUF_START(0),
    56. .buf_size= VIDW_BUF_SIZE(0),
    57. .buf_end= VIDW_BUF_END(0),
    58. .palette = {
    59. [0] = 0x400,
    60. [1] = 0x800,
    61. [2] = 0x300,
    62. [3] = 0x320,
    63. [4] = 0x340,
    64. },
    65. .has_prtcon= 1,
    66. .has_clksel= 1,
    67. },
    68. .win[0]= &s3c_fb_data_64xx_wins[0],
    69. .win[1]= &s3c_fb_data_64xx_wins[1],
    70. .win[2]= &s3c_fb_data_64xx_wins[2],
    71. .win[3]= &s3c_fb_data_64xx_wins[3],
    72. .win[4]= &s3c_fb_data_64xx_wins[4],
    73. };
    4.2 s3c_fb_probe函数分析

    点击(此处)折叠或打开

    1. static int __devinit s3c_fb_probe(struct platform_device *pdev)
    2. {
    3.     const struct platform_device_id *platid;
    4.     struct s3c_fb_driverdata *fbdrv;
    5.     struct device *dev = &pdev->dev;
    6.     struct s3c_fb_platdata *pd;
    7.     struct s3c_fb *sfb;
    8.     struct resource *res;
    9.     int win;
    10.     int ret = 0;
    11.  
    12.     //platid指向平台设备结构体里的id_entry成员,即 platid = pdev->id_entry;
    13.     platid = platform_get_device_id(pdev)
    14.     //fbdrv指向平台设备结构体id_entry项的driver_data成员
    15.     fbdrv = (struct s3c_fb_driverdata *)platid->driver_data;
    16.  
    17.     //判断是否超出最大硬件支持的最大窗口数
    18.     if (fbdrv->variant.nr_windows > S3C_FB_MAX_WIN) {
    19.         dev_err(dev, "too many windows, cannot attach ");
    20.         return -EINVAL;
    21.     }
    22.  
    23.     //指向平台设备的平台数据
    24.     pd = pdev->dev.platform_data;
    25.     if (!pd) {
    26.         dev_err(dev, "no platform data specified ");
    27.         return -EINVAL;
    28.     }
    29.  
    30.     //1. 给s3c_fb结构体分配内存
    31.     sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
    32.     if (!sfb) {
    33.         dev_err(dev, "no memory for framebuffers ");
    34.         return -ENOMEM;
    35.     }
    36.     dev_dbg(dev, "allocate new framebuffer %p ", sfb);
    37.     
    38.     //2. 设置s3c_fb结构体
    39.     sfb->dev = dev;   //指向设备
    40.     sfb->pdata = pd;   //指向平台设备的平台数据
    41.     sfb->variant = fbdrv->variant; //s3c_fb_variant结构体拷贝(结构体完全一样可直接拷贝)
    42.     spin_lock_init(&sfb->slock);   //初始化自旋锁
    43.  
    44.     //3. 获取并使能模块总时钟
    45.     sfb->bus_clk = clk_get(dev, "lcd");//找到对应的bus clock,模块总时钟
    46.     if (IS_ERR(sfb->bus_clk)) {
    47.         dev_err(dev, "failed to get bus clock ");
    48.         ret = PTR_ERR(sfb->bus_clk);
    49.         goto err_sfb;
    50.     }
    51.     clk_enable(sfb->bus_clk);//使能模块总时钟
    52.     if (!sfb->variant.has_clksel) {//判断driver_data里是否已定义源时钟
    53.         sfb->lcd_clk = clk_get(dev, "sclk_fimd");//未定义,用“sclk_fimd”去clock文件里
    54.         if (IS_ERR(sfb->lcd_clk)) {
    55.             dev_err(dev, "failed to get lcd clock ");
    56.             ret = PTR_ERR(sfb->lcd_clk);
    57.             goto err_bus_clk;
    58.         }
    59.         clk_enable(sfb->lcd_clk); //使能clock文件里找到的时钟源
    60.     }
    61.     pm_runtime_enable(sfb->dev); //使能设备运行时电源管理
    62.     
    63.     //4. 获取平台设备数据 
    64.     //获取资源起始地址、结束地址,是显示控制器寄存器组地址
    65.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    66.     if (!res) {
    67.         dev_err(dev, "failed to find registers ");
    68.         ret = -ENOENT;
    69.         goto err_lcd_clk;
    70.     }
    71.  
    72.     //为显示控制器寄存器组分配内存
    73.     sfb->regs_res = request_mem_region(res->start, resource_size(res),
    74.                      dev_name(dev));
    75.     if (!sfb->regs_res) {
    76.         dev_err(dev, "failed to claim register region ");
    77.         ret = -ENOENT;
    78.         goto err_lcd_clk;
    79.     }
    80.  
    81.     //把寄存器组地址映射到内存
    82.     //:这里使用ioremap,所以,BSP中不需要编写针对LCD的I/O内存静态映射
    83.     //   即static struct map_desc jason6410_iodesc[]{};里面这部分。
    84.     sfb->regs = ioremap(res->start, resource_size(res));
    85.     if (!sfb->regs) {
    86.         dev_err(dev, "failed to map registers ");
    87.         ret = -ENXIO;
    88.         goto err_req_region;
    89.     }
    90.  
    91.     //获取资源中的中断部分
    92.     res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    93.     if (!res) {
    94.         dev_err(dev, "failed to acquire irq resource ");
    95.         ret = -ENOENT;
    96.         goto err_ioremap;
    97.     }
    98.     sfb->irq_no = res->start;
    99.     ret = request_irq(sfb->irq_no, s3c_fb_irq,//注册中断处理函数
    100.              0, "s3c_fb", sfb);
    101.     if (ret) {
    102.         dev_err(dev, "irq request failed ");
    103.         goto err_ioremap;
    104.     }
    105.     dev_dbg(dev, "got resources (regs %p), probing windows ", sfb->regs);
    106.  
    107.     //pdev->dev->p->driver_data = sfb
    108.     platform_set_drvdata(pdev, sfb);
    109.     //运行时恢复操作的入口
    110.     pm_runtime_get_sync(sfb->dev);
    111.     /* setup gpio and output polarity controls */
    112.     //5. 设置寄存器组
    113.     pd->setup_gpio(); //设置数据线的GPIO,pd见23行,s3c64xx_fb_gpio_setup_24bpp,见BSP
    114.     writel(pd->vidcon1, sfb->regs + VIDCON1); //写VIDCON1寄存器
    115.     /* zero all windows before we do anything */
    116.     for (win = 0; win < fbdrv->variant.nr_windows; win++) //复位所有窗口寄存器
    117.         s3c_fb_clear_win(sfb, win);
    118.     /* initialise colour key controls */ //初始化
    119.     for (win = 0; win < (fbdrv->variant.nr_windows - 1); win++) {
    120.         void __iomem *regs = sfb->regs + sfb->variant.keycon;
    121.         regs += (win * 8);//GNU下空指针可以算数运算,并且算法操作与char *一致
    122.         writel(0xffffff, regs + WKEYCON0); //详见S3C6410X.pdf 516页
    123.         writel(0xffffff, regs + WKEYCON1);
    124.     }
    125.     /* we have the register setup, start allocating framebuffers */
    126.     //6. 设置完寄存器,开始分配帧缓冲
    127.     for (win = 0; win < fbdrv->variant.nr_windows; win++) {
    128.         if (!pd->win[win])
    129.             continue;
    130.         if (!pd->win[win]->win_mode.pixclock) //如果未定义像素时钟,在此计算
    131.             s3c_fb_missing_pixclock(&pd->win[win]->win_mode); //计算像素时钟
    132.  
    133. //注册硬件窗口,下面展开细说
    134.         ret = s3c_fb_probe_win(sfb, win, fbdrv->win[win],
    135.                  &sfb->windows[win]);
    136.         if (ret < 0) {
    137.             dev_err(dev, "failed to create window %d ", win);
    138.             for (; win >= 0; win--)
    139.                 s3c_fb_release_win(sfb, sfb->windows[win]);
    140.             goto err_irq;
    141.         }
    142.     }
    143.  
    144.     //再一次,同line 112/114
    145.     platform_set_drvdata(pdev, sfb);
    146.     pm_runtime_put_sync(sfb->dev);
    147.     return 0;
    148. err_irq:
    149.     free_irq(sfb->irq_no, sfb);
    150. err_ioremap:
    151.     iounmap(sfb->regs);
    152. err_req_region:
    153.     release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
    154. err_lcd_clk:
    155.     if (!sfb->variant.has_clksel) {
    156.         clk_disable(sfb->lcd_clk);
    157.         clk_put(sfb->lcd_clk);
    158.     }
    159. err_bus_clk:
    160.     clk_disable(sfb->bus_clk);
    161.     clk_put(sfb->bus_clk);
    162. err_sfb:
    163.     kfree(sfb);
    164.     return ret;
    165. }
    4.3 s3c_fb_probe_win函数分析(注册硬件窗口)

    点击(此处)折叠或打开

    1. /**
    2.  * s3c_fb_probe_win() - register an hardware window
    3.  * @sfb: The base resources for the hardware
    4.  * @variant: The variant information for this window.
    5.  * @res: Pointer to where to place the resultant window.
    6.  *
    7.  * Allocate and do the basic initialisation for one of the hardware's graphics
    8.  * windows.
    9.  */
    10. static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
    11.                  struct s3c_fb_win_variant *variant,
    12.                  struct s3c_fb_win **res)
    13. {
    14.     struct fb_var_screeninfo *var;
    15.     struct fb_videomode *initmode;
    16.     struct s3c_fb_pd_win *windata;
    17.     struct s3c_fb_win *win;
    18.     struct fb_info *fbinfo;
    19.     int palette_size;
    20.     int ret;
    21.     dev_dbg(sfb->dev, "probing window %d, variant %p ", win_no, variant);
    22.     init_waitqueue_head(&sfb->vsync_info.wait);    //初始化等待队列头
    23.     palette_size = variant->palette_sz * 4;    //设置调色板大小
    24.  
    25.     //1.创建fb_info结构体,并分配驱动私有数据
    26.     fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
    27.                  palette_size * sizeof(u32), sfb->dev);
    28.     if (!fbinfo) {
    29.         dev_err(sfb->dev, "failed to allocate framebuffer ");
    30.         return -ENOENT;
    31.     }
    32.     
    33. //windata指向平台设备驱动私有数据里的win[win_no]成员,这里是BSP中的jason6410_fb_win0结构体
    34. //initmode指向jason6410_fb_win结构体里的win_mode成员
    35. 点击(此处)折叠或打开

      1. static struct s3c_fb_pd_win jason6410_fb_win0 = {
      2.     /* this is to ensure we use win0 */
      3.     .win_mode    = {
      4. #if 0
      5.         .pixclock    = 115440,
      6. #endif
      7.         .left_margin    = 0x03,
      8.         .right_margin    = 0x02,
      9.         .upper_margin    = 0x01,
      10.         .lower_margin    = 0x01,
      11.         .hsync_len    = 0x28,
      12.         .vsync_len    = 0x01,
      13.         .xres        = 480,
      14.         .yres        = 272,
      15.     },
      16.     .max_bpp    = 32,
      17.     .default_bpp    = 16,
      18. };
    36.     windata = sfb->pdata->win[win_no];
    37.     initmode = &windata->win_mode;
    38.     WARN_ON(windata->max_bpp == 0);//调用dump_stack,打印堆栈信息
    39.     WARN_ON(windata->win_mode.xres == 0);
    40.     WARN_ON(windata->win_mode.yres == 0);
    41.  
    42.     //2. 帧缓冲每个窗口的s3c_fb_win结构体设置
    43.     win = fbinfo->par; //见代码30行分配fb_info结构体部分,在那fbinfo->par已指向驱动私有数据
    44.     *res = win;//*res指向win
    45.     var = &fbinfo->var; //var指向fb_var_screeninfo结构体
    46.     win->variant = *variant;//结构体复制(同一类型结构体可以复制)
    47.     win->fbinfo = fbinfo;//fbinfo指向fb_info结构体
    48.     win->parent = sfb;//parent指向s3c_fb结构体
    49.     win->windata = windata;     //windata指向s3c_fb_pd_win结构体
    50.     win->index = win_no;//编号
    51.     win->palette_buffer = (u32 *)(win + 1); //指向调色板缓冲区
    52.  
    53.     //3. 为帧缓冲的窗口分配显示内存
    54.     ret = s3c_fb_alloc_memory(sfb, win);
    55.     if (ret) {
    56.         dev_err(sfb->dev, "failed to allocate display memory ");
    57.         return ret;
    58.     }
    59.     /* setup the r/b/g positions for the window's palette */
    60.     //4. 为窗口调色板设置r/g/b的位置,这里的palette_16bpp为初始化值1,程序中未对其赋值
    61. 点击(此处)折叠或打开

      1. //该结构体位于4.1节 
      2. struct s3c_fb_win_variant {
      3.     unsigned int    has_osd_c:1;
      4.     unsigned int    has_osd_d:1;
      5.     unsigned int    has_osd_alpha:1;
      6.     unsigned int    palette_16bpp:1;
      7.     unsigned short    osd_size_off;
      8.     unsigned short    palette_sz;
      9.     u32        valid_bpp;
      10. };
    62.     if (win->variant.palette_16bpp) {
    63.         /* Set RGB 5:6:5 as default */
    64.         win->palette.r.offset = 11;
    65.         win->palette.r.length = 5;
    66.         win->palette.g.offset = 5;
    67.         win->palette.g.length = 6;
    68.         win->palette.b.offset = 0;
    69.         win->palette.b.length = 5;
    70.     } else {
    71.         /* Set 8bpp or 8bpp and 1bit alpha */
    72.         win->palette.r.offset = 16;
    73.         win->palette.r.length = 8;
    74.         win->palette.g.offset = 8;
    75.         win->palette.g.length = 8;
    76.         win->palette.b.offset = 0;
    77.         win->palette.b.length = 8;
    78.     }
    79.     /* setup the initial video mode from the window */
    80.     //5. 设置初始视频模式,填充结构体fbinfo
    81.     //将fb_videomode结构体中成员赋值给fb_var_screeninfo结构体对应成员
    82.     fb_videomode_to_var(&fbinfo->var, initmode);
    83.     fbinfo->fix.type    = FB_TYPE_PACKED_PIXELS;
    84.     fbinfo->fix.accel    = FB_ACCEL_NONE;
    85.     fbinfo->var.activate    = FB_ACTIVATE_NOW;
    86.     fbinfo->var.vmode    = FB_VMODE_NONINTERLACED;
    87.     fbinfo->var.bits_per_pixel = windata->default_bpp;
    88.     fbinfo->fbops        = &s3c_fb_ops;
    89.     fbinfo->flags        = FBINFO_FLAG_DEFAULT;
    90.     fbinfo->pseudo_palette = &win->pseudo_palette;
    91.     /* prepare to actually start the framebuffer */
    92.     //6. 检查可变参数,帧缓冲层核实信息,并根据硬件能力更新几种信息。
    93.     ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
    94.     if (ret < 0) {
    95.         dev_err(sfb->dev, "check_var failed on initial video params ");
    96.         return ret;
    97.     }
    98.     /* create initial colour map */
    99.     //7. 分配和设置fb_cmap结构体,该结构体记录设备无关的颜色表信息
    100.     ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
    101.     if (ret == 0)
    102.         fb_set_cmap(&fbinfo->cmap, fbinfo);
    103.     else
    104.         dev_err(sfb->dev, "failed to allocate fb cmap ");
    105.     
    106.     //8. 设置帧缓冲模式
    107.     s3c_fb_set_par(fbinfo);
    108.     dev_dbg(sfb->dev, "about to register framebuffer ");
    109.     /* run the check_var and set_par on our configuration. */
    110.  
    111.     //9. 注册一个帧缓冲设备
    112.     ret = register_framebuffer(fbinfo);
    113.     if (ret < 0) {
    114.         dev_err(sfb->dev, "failed to register framebuffer ");
    115.         return ret;
    116.     }
    117.     dev_info(sfb->dev, "window %d: fb %s ", win_no, fbinfo->fix.id);
    118.     return 0;
    119. }
     
    5、帧缓冲设备的用户空间访问
    运行如下代码,在LCD显示屏上绘制R/G/B这三种颜色的由浅入深的变化情况。

    点击(此处)折叠或打开

    1. /*
    2.  * S3C6410 framebuffer test programs
    3.  */
    4. #include <unistd.h>
    5. #include <stdlib.h>
    6. #include <stdio.h>
    7. #include <fcntl.h>
    8. #include <linux/fb.h>
    9. #include <sys/mman.h>
    10. int main()
    11. {
    12.     int fbfd = 0;
    13.     struct fb_var_screeninfo vinfo;
    14.     unsigned long screensize = 0;
    15.     char *fbp = 0;
    16.     int x = 0, y = 0;
    17.     int i = 0;
    18.     // Open the file for reading and writing
    19.     fbfd = open("/dev/fb0", O_RDWR);
    20.     if (!fbfd) {
    21.         printf("Error: cannot open framebuffer device. ");
    22.         exit(1);
    23.     }
    24.     printf("The framebuffer device was opened successfully. ");
    25.     // Get variable screen information
    26.     if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
    27.         printf("Error reading variable information. ");
    28.         exit(1);
    29.     }
    30.     printf("%dx%d, %dbpp ", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
    31.     if (vinfo.bits_per_pixel != 16) {
    32.         printf("Error: not supported bits_per_pixel, it only supports 16 bit color ");
    33.         exit(1);
    34.     }
    35.     // Figure out the size of the screen in bytes
    36.     screensize = vinfo.xres * vinfo.yres * 2;
    37.     // Map the device to memory
    38.     fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
    39.         fbfd, 0);
    40.     if ((int)fbp == -1) {
    41.         printf("Error: failed to map framebuffer device to memory. ");
    42.         exit(4);
    43.     }
    44.     printf("The framebuffer device was mapped to memory successfully. ");
    45.     // Draw 3 rect with graduated RED/GREEN/BLUE
    46.     for (i = 0; i < 3; i++) {
    47.         for (y = i * (vinfo.yres / 3); y < (i + 1) * (vinfo.yres / 3); y++) {
    48.             for (x = 0; x < vinfo.xres; x++) {
    49.                 long location = x * 2 + y * vinfo.xres * 2;
    50.                 int r = 0, g = 0, b = 0;
    51.                 unsigned short rgb;
    52.                 if (i == 0)
    53.                     r = ((x * 1.0) / vinfo.xres) * 32;
    54.                 if (i == 1)
    55.                     g = ((x * 1.0) / vinfo.xres) * 64;
    56.                 if (i == 2)
    57.                     b = ((x * 1.0) / vinfo.xres) * 32;
    58.                 rgb = (r << 11) | (g << 5) | b;
    59.                 *((unsigned short*)(fbp + location)) = rgb;
    60.             }
    61.         }
    62.     }
    63.     munmap(fbp, screensize);
    64.     close(fbfd);
    65.     return 0;
    66. }
    测试方法(LCD尺寸有所不同,仅作参考):
     
     
     
     
     
    二、内核修改
    下列代码是I/O静态内存映射,s3c-fb.c里通过ioremap映射需配置的寄存器,所以无需做静态内存映射,所以内核部分可不做任何修改(不包括BSP)。如果驱动里用的是虚拟地址,则必须使用下列代码。

    点击(此处)折叠或打开

    1. gedit arch/arm/plat-samsung/include/plat/map-base.
    2. line 39 add:
    3. #define S3C_VA_LCD    S3C_ADDR(0x01100000) /* LCD */
    在BSP中添加:

    点击(此处)折叠或打开

    1. static struct map_desc jason6410_iodesc[] = {
    2.     {
    3.         /* LCD support */
    4.         .virtual = (unsigned long)S3C_VA_LCD,//虚拟地址
    5.         .pfn = __phys_to_pfn(S3C_PA_FB),//物理地址
    6.         .length = SZ_16K,
    7.         .type = MT_DEVICE,
    8.     },
    9. };
    10.  
    11. static void __init jason6410_map_io(void)
    12. {
    13. s3c64xx_init_io(jason6410_iodesc, ARRAY_SIZE(jason6410_iodesc)); //初始化
    14. ......
    15.  
    16. }
     
    三、内核配置
     

    点击(此处)折叠或打开

    1. Device Drivers --->
    2.     Graphics support --->
    3.         <*> Support for frame buffer devices --->
    4.             <*> Samsung S3C framebuffer support
    5. Device Drivers --->
    6.     Graphics support --->
    7.         [ ] Backlight & LCD device support --->
    8. Device Drivers --->
    9.     Graphics support --->
    10.         Console display driver support --->
    11.             <*> Framebuffer Console support
    12. Device Drivers --->
    13.     Graphics support --->
    14.         [*] Bootup logo --->
    四、启动Logo修改
    1. 找到自己喜欢的图片,用Photoshop裁剪为屏幕尺寸大小,这里是480*272;
    2. PS软件里选 文件 ---> 存储为,在弹出框里输入保存名,保存类型选BMP格式;按确定后会弹出如下窗口,如红色方框内选择,选择深度为24位。产生logo.bmp(480*272,24bpp),在此 logo.zip   
    3. 重复步骤2中前面步骤,在最后的弹出框点选高级模式,并选如下图所示,产生logo_cat.bmp(480*272,16bpp,R/G/B:5/6/5),该图用于"cat logo_cat.bmp > /dev/fb0"演示。 logo_cat.zip   
     
    4. 接下来的步骤在Linux下进行,将步骤2生成的logo.bmp并不能用在内核中,需做进一步修改,先把它拷贝到虚拟机里某一目录下,执行如下转换。

    点击(此处)折叠或打开

    1. # bmptoppm logo.bmp > logo.ppm
    2. # ppmquant 224 logo.ppm > logo_224.ppm
    3. # pnmnoraw logo_224.ppm > logo_linux_clut224.ppm
    5. 将上一步骤中生成的logo_linux_clut224.ppm拷贝到内核目录:drivers/video/logo/覆盖原有图片。
    6. 如果已经编译过内核,直接再次编译,图片很有可能是原来的或者是没显示,可以执行如下命令清楚中间结果,而不必用make distclean清空,实在不行再用此命令,有时会有的,不知为何,呵呵。

    点击(此处)折叠或打开

    1. # rm drivers/video/logo/.l*
    7. 执行如下命令,烧写内核,就能看到启动界面。

    点击(此处)折叠或打开

    1. make uImage -j4
     8. 内核挂上文件系统后,传入步骤3中产生的logo_cat.bmp,执行如下命令,能看到图片。现在还有点问题,图片倒过来的,并且水平有偏移。

    点击(此处)折叠或打开

    1. cat logo_cat.bmp > /dev/fb0
    注意:在内核里必须勾选如下选项,不选择,是显示不了启动图片的。

    点击(此处)折叠或打开

    1. Device Drivers --->
    2.     Graphics support --->
    3.         Console display driver support --->
    4.             <*> Framebuffer Console support
    附录1:启动界面
     
     
    附录2:cat logo_cat.bmp > /dev/fb0 后屏幕显示
     
     
    五、启动QT
     现在做的主要是内核移植,文件系统用的还是友善自带的,但是如上修改后,界面程序还是启动不了,且无人任何错误信息。文件系统里是有保证界面启动的库函数的,所以问题应该出现在驱动或者内核配置上。
    友 善自带的文件系统里有三个界面程序,我试着打开qt4(“/bin/qt4 &” 命令)那个界面时,有错误提示了,先是socket相关错误,就照着友善2.6.38内核的配置,配置了Networking support下的内核选项。接着报信号量错误,就照着友善的配置在Gernel Setup下配置内核选项。现在能启动界面了。
    还 有一个问题是,友善文件系统里自带的rcS有输出信息输出到显示屏上,不好看。就在文件系统里的etc/init.d/rcS里,把所有 "> /dev/tty1"都注释掉,这样这些打印信息只会在串口终端里显示,不会影响界面显示了。用如下命令生成新的ubi文件系统。

    点击(此处)折叠或打开

    1. # mkubimage-slc  rootfs_qtopia_qt4  rootfs_qtopia_qt4-slc.ubi
  • 相关阅读:
    Android——用Activity和Service实现简单的音乐播放器
    Android——indexof()
    Android——简易计算器(转)
    Android——计算器第一次完善
    Android——Service
    Android——ViewPager滑动背景渐变(自定义view,ViewPager)
    Android ——利用OnDraw实现自定义View(转)
    Android——自定义视图(一)转
    OpenERP在哪储存附件?
    销售预付款达到指定比例方可发货
  • 原文地址:https://www.cnblogs.com/qiaoqiao2003/p/3712006.html
Copyright © 2011-2022 走看看