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

一、BSP修改及其分析
 
1. BSP中直接配置的四个寄存器
S3C6410数据手册的第14.5部分是显示控制器的编程模型部分,图1是开始部分截图。如第一行所说,这些寄存器是配置显示控制器用的。所以,所有的寄存器设置都围绕这些寄存器进行。
      其中前面四个寄存器SPCON、MOFPCON、VIDCON0与VIDCON0,直接在BSP中进行配置
图 1
 
A. SPCON和MOFPCON寄存器:如下代码中,配置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. #define MIFPCON_LCD_BYPASS(1 << 3)
B、VIDCON0和VIDCON1寄存器:如下代码中,配置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. //配置LCD数据信号线GPIO
  9. extern void s3c64xx_fb_gpio_setup_24bpp(void)
  10. {
  11. s3c_gpio_cfgrange_nopull(S3C64XX_GPI(0), 16, S3C_GPIO_SFN(2));//GPI
  12. s3c_gpio_cfgrange_nopull(S3C64XX_GPJ(0), 12, S3C_GPIO_SFN(2));//GPJ
  13. }

点击(此处)折叠或打开

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

点击(此处)折叠或打开

  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. //platform_match_id函数
  16. static const struct platform_device_id *platform_match_id(
  17. const struct platform_device_id *id,
  18. struct platform_device *pdev)
  19. {
  20. while (id->name[0]) {
  21. if (strcmp(pdev->name, id->name) == 0) {
  22. pdev->id_entry = id;
  23. return id;
  24. }
  25. id++;
  26. }
  27. return NULL;
  28. }

点击(此处)折叠或打开

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

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\n", win_no, variant);
  22. init_waitqueue_head(&sfb->vsync_info.wait);    //初始化等待队列头
  23. palette_size = variant->palette_sz * 4;    //设置调色板大小
  24. //1.创建fb_info结构体,并分配驱动私有数据
  25. fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
  26. palette_size * sizeof(u32), sfb->dev);
  27. if (!fbinfo) {
  28. dev_err(sfb->dev, "failed to allocate framebuffer\n");
  29. return -ENOENT;
  30. }
  31. //windata指向平台设备驱动私有数据里的win[win_no]成员,这里是BSP中的jason6410_fb_win0结构体
  32. //initmode指向jason6410_fb_win结构体里的win_mode成员
  33. 点击(此处)折叠或打开

    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. };
  34. windata = sfb->pdata->win[win_no];
  35. initmode = &windata->win_mode;
  36. WARN_ON(windata->max_bpp == 0);//调用dump_stack,打印堆栈信息
  37. WARN_ON(windata->win_mode.xres == 0);
  38. WARN_ON(windata->win_mode.yres == 0);
  39. //2. 帧缓冲每个窗口的s3c_fb_win结构体设置
  40. win = fbinfo->par; //见代码30行分配fb_info结构体部分,在那fbinfo->par已指向驱动私有数据
  41. *res = win;//*res指向win
  42. var = &fbinfo->var; //var指向fb_var_screeninfo结构体
  43. win->variant = *variant;//结构体复制(同一类型结构体可以复制)
  44. win->fbinfo = fbinfo;//fbinfo指向fb_info结构体
  45. win->parent = sfb;//parent指向s3c_fb结构体
  46. win->windata = windata;     //windata指向s3c_fb_pd_win结构体
  47. win->index = win_no;//编号
  48. win->palette_buffer = (u32 *)(win + 1); //指向调色板缓冲区
  49. //3. 为帧缓冲的窗口分配显示内存
  50. ret = s3c_fb_alloc_memory(sfb, win);
  51. if (ret) {
  52. dev_err(sfb->dev, "failed to allocate display memory\n");
  53. return ret;
  54. }
  55. /* setup the r/b/g positions for the window's palette */
  56. //4. 为窗口调色板设置r/g/b的位置,这里的palette_16bpp为初始化值1,程序中未对其赋值
  57. 点击(此处)折叠或打开

    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:;
    7. unsigned short    osd_size_off;
    8. unsigned short    palette_sz;
    9. u32        valid_bpp;
    10. };
  58. if (win->variant.palette_16bpp) {
  59. /* Set RGB 5:6:5 as default */
  60. win->palette.r.offset = 11;
  61. win->palette.r.length = 5;
  62. win->palette.g.offset = 5;
  63. win->palette.g.length = 6;
  64. win->palette.b.offset = 0;
  65. win->palette.b.length = 5;
  66. } else {
  67. /* Set 8bpp or 8bpp and 1bit alpha */
  68. win->palette.r.offset = 16;
  69. win->palette.r.length = 8;
  70. win->palette.g.offset = 8;
  71. win->palette.g.length = 8;
  72. win->palette.b.offset = 0;
  73. win->palette.b.length = 8;
  74. }
  75. /* setup the initial video mode from the window */
  76. //5. 设置初始视频模式,填充结构体fbinfo
  77. //将fb_videomode结构体中成员赋值给fb_var_screeninfo结构体对应成员
  78. fb_videomode_to_var(&fbinfo->var, initmode);
  79. fbinfo->fix.type    = FB_TYPE_PACKED_PIXELS;
  80. fbinfo->fix.accel    = FB_ACCEL_NONE;
  81. fbinfo->var.activate    = FB_ACTIVATE_NOW;
  82. fbinfo->var.vmode    = FB_VMODE_NONINTERLACED;
  83. fbinfo->var.bits_per_pixel = windata->default_bpp;
  84. fbinfo->fbops        = &s3c_fb_ops;
  85. fbinfo->flags        = FBINFO_FLAG_DEFAULT;
  86. fbinfo->pseudo_palette = &win->pseudo_palette;
  87. /* prepare to actually start the framebuffer */
  88. //6. 检查可变参数,帧缓冲层核实信息,并根据硬件能力更新几种信息。
  89. ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
  90. if (ret < 0) {
  91. dev_err(sfb->dev, "check_var failed on initial video params\n");
  92. return ret;
  93. }
  94. /* create initial colour map */
  95. //7. 分配和设置fb_cmap结构体,该结构体记录设备无关的颜色表信息
  96. ret = fb_alloc_cmap(&fbinfo->cmap, win->variant.palette_sz, 1);
  97. if (ret == 0)
  98. fb_set_cmap(&fbinfo->cmap, fbinfo);
  99. else
  100. dev_err(sfb->dev, "failed to allocate fb cmap\n");
  101. //8. 设置帧缓冲模式
  102. s3c_fb_set_par(fbinfo);
  103. dev_dbg(sfb->dev, "about to register framebuffer\n");
  104. /* run the check_var and set_par on our configuration. */
  105. //9. 注册一个帧缓冲设备
  106. ret = register_framebuffer(fbinfo);
  107. if (ret < 0) {
  108. dev_err(sfb->dev, "failed to register framebuffer\n");
  109. return ret;
  110. }
  111. dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
  112. return 0;
  113. }
 
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.\n");
  22. exit(1);
  23. }
  24. printf("The framebuffer device was opened successfully.\n");
  25. // Get variable screen information
  26. if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
  27. printf("Error reading variable information.\n");
  28. exit(1);
  29. }
  30. printf("%dx%d, %dbpp\n", 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\n");
  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.\n");
  42. exit(4);
  43. }
  44. printf("The framebuffer device was mapped to memory successfully.\n");
  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.h
  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. static void __init jason6410_map_io(void)
  11. {
  12. s3c64xx_init_io(jason6410_iodesc, ARRAY_SIZE(jason6410_iodesc)); //初始化
  13. ......
  14. }
 
三、内核配置
 

点击(此处)折叠或打开

  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

【转载】帧缓冲驱动程序分析及其在BSP上的添加的更多相关文章

  1. OpenGL核心技术之帧缓冲

    笔者介绍:姜雪伟.IT公司技术合伙人,IT高级讲师.CSDN社区专家.特邀编辑.畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  2. RT-Thread下的串口驱动程序分析【转载】

    编写本文稿的目的,在于通过分析stm32平台上的串口中断源码,学习 RTT中如何编写中断处理程序 如何编写RTT设备驱动接口代码 了解串行设备的常见处理机制 先以RTT官方源码中的STM32 BSP包 ...

  3. [国嵌攻略][143][LCD驱动程序分析]

    LCD驱动程序分析 LCD驱动程序代码在/drivers/video/s3c2410fb.c文件中,在该驱动的s3c2410fb_init中注册了平台驱动,该驱动的初始化代码在s3c24xxfc_pr ...

  4. android 电容屏(三):驱动调试之驱动程序分析篇

    平台信息: 内核:linux3.4.39系统:android4.4 平台:S5P4418(cortex a9) 作者:瘋耔(欢迎转载,请注明作者) 欢迎指正错误,共同学习.共同进步!! 关注博主新浪博 ...

  5. 【转】android 电容屏(三):驱动调试之驱动程序分析篇

    关键词:android  电容屏 tp 工作队列 中断 坐点计算  电容屏主要参数平台信息:内核:linux2.6/linux3.0系统:android/android4.0  平台:S5PV310( ...

  6. Microsoft宣布为Power BI提供AI模型构建器,关键驱动程序分析和Azure机器学习集成

    微软的Power BI现在是一种正在大量结合人工智能(AI)的商业分析服务,它使用户无需编码经验或深厚的技术专长就能够创建报告,仪表板等.近日西雅图公司宣布推出几款新的AI功能,包括图像识别和文本分析 ...

  7. linux PWM蜂鸣器移植以及驱动程序分析【转】

    本文转载自:https://blog.csdn.net/lxllinux/article/details/80885331 一.关于PWM:        PWM(Pulse Width Modula ...

  8. c# GDI画图 双缓冲画图分析

    双缓冲绘图分析  1.Windows 绘图原理  我们在 Windows 环境下看到各种元素,如菜单.按钮.窗口.图像,从根本上说,都是“画”出来的.这时的屏幕,就相当于一块黑板,而 Windows ...

  9. Linux中LCD设备驱动-framebuffer(帧缓冲)【】

    转自:https://blog.csdn.net/linux_devices_driver/article/details/7079442 1.framebuffer 帧缓冲     帧缓冲(fram ...

随机推荐

  1. C#中用鼠标移动页面功能的实现(代码控制滚动条)

    项目中需要实现以下功能: 打印预览控件中,可以用鼠标拖动页面,以查看超出显示范围之外的部分内容. 该功能本来可以通过拉动水平和垂直滚动条来实现,但实际使用中,用户更趋向于直接用鼠标拖动页面来实现,很多 ...

  2. Java内存区域与模拟内存区域异常

    我把Java的内存区域画了一张思维导图,以及各区域的主要功能. 模拟Java堆溢出 Java堆用于存储对象实例.仅仅要不断地创建对象而且保证GC ROOTS到对象之间有可达路径避免被回收机制清除.就能 ...

  3. 从头认识java-14.2 进一步了解数组

    这一章节我们来全面了解一下数组. 1.数组在初始化之前.我们不能使用他的引用来做不论什么事情. package com.ray.ch14; public class Test { public sta ...

  4. dede程序打开install安装时出现dir

    刚在网上找了个开源的dede程序,打开install安装时出现dir.解决方法例如以下: 1.删除install下的index.html和install_lock.txt(有的是要删除install. ...

  5. 《C陷阱与缺陷》学习笔记(一)

    前言和导读 "得心应手的工具在初学时的困难程度往往超过那些easy上手的工具."比較认同这句话. 我至今认为自己事实上还是个刚入了门的刚開始学习的人. 第一章 "词法&q ...

  6. iOS 自己定义页面的切换动画与交互动画 By Swift

    在iOS7之前,开发人员为了寻求自己定义Navigation Controller的Push/Pop动画,仅仅能受限于子类化一个UINavigationController,或是用自己定义的动画去覆盖 ...

  7. git 操作分支

    1. git 查看本地分支:git branch 2. git 查看所有分支:git branch -a 3. git 新建本地分支:git branch branchName 4. git 新建分支 ...

  8. mybatis的两种分页方式:RowBounds和PageHelper

    原理:拦截器. 使用方法: RowBounds:在mapper.java中的方法中传入RowBounds对象. RowBounds rowBounds = new RowBounds(offset, ...

  9. jdk并发工具包之锁

    1.cynchronized扩展:可重锁入ReentrantLock ReentrantLock是通过cas算法实现的 RenntrantLock lock=new ReentrantLock(); ...

  10. emacs 简记

    简介 Emacs作为神的编辑器,不用介绍了吧,说点感受. 用了一段时间了,总体感觉其实Emacs是很简单的,甚至比vim还简单,因为在X环境下,打开后可以就像记事本一样使用.但是,使用Emacs的人一 ...