Chinaunix首页 | 论坛 | 博客
  • 博客访问: 459480
  • 博文数量: 40
  • 博客积分: 1410
  • 博客等级: 军士长
  • 技术积分: 1396
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-22 19:26
个人简介

嵌入式系统工程师,从事视频、图像、网络、虚拟化等方面的底层软件开发与优化。

文章存档

2014年(4)

2013年(10)

2012年(14)

2011年(12)

分类: LINUX

2012-04-21 15:52:48

一、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. Video Mode Timings
  22.   +----------+---------------------------------------------+----------+-------+
  23.   |          |                ↑                            |          |       |
  24.   |          |                |upper_margin                |          |       |
  25.   |          |                ↓                            |          |       |
  26.   +----------###############################################----------+-------+
  27.   |          #                ↑                            #          |       |
  28.   |          #                |                            #          |       |
  29.   |          #                |                            #          |       |
  30.   |          #                |                            #          |       |
  31.   |   left   #                |                            #  right   | hsync |
  32.   |  margin  #                |       xres                 #  margin  |  len  |
  33.   |<-------->#<---------------+--------------------------->#<-------->|<----->|
  34.   |          #                |                            #          |       |
  35.   |          #                |                            #          |       |
  36.   |          #                |                            #          |       |
  37.   |          #                |yres                        #          |       |
  38.   |          #                |                            #          |       |
  39.   |          #                |                            #          |       |
  40.   |          #                |                            #          |       |
  41.   |          #                |                            #          |       |
  42.   |          #                |                            #          |       |
  43.   |          #                |                            #          |       |
  44.   |          #                |                            #          |       |
  45.   |          #                |                            #          |       |
  46.   |          #                ↓                            #          |       |
  47.   +----------###############################################----------+-------+
  48.   |          |                ↑                            |          |       |
  49.   |          |                |lower_margin                |          |       |
  50.   |          |                ↓                            |          |       |
  51.   +----------+---------------------------------------------+----------+-------+
  52.   |          |                ↑                            |          |       |
  53.   |          |                |vsync_len                   |          |       |
  54.   |          |                ↓                            |          |       |
  55.   +----------+---------------------------------------------+----------+-------+

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. static struct s3c_fb_pd_win jason6410_fb_win0 = {
  79. /* this is to ensure we use win0 */
  80. .win_mode = {
  81. #if 0
  82. .pixclock = 115440,
  83. #endif
  84. .left_margin = 0x03,
  85. .right_margin = 0x02,
  86. .upper_margin = 0x01,
  87. .lower_margin = 0x01,
  88. .hsync_len = 0x28,
  89. .vsync_len = 0x01,
  90. .xres = 480,
  91. .yres = 272,
  92. },
  93. .max_bpp = 32,
  94. .default_bpp = 16,
  95. };

点击(此处)折叠或打开

  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. static struct s3c_fb_pd_win jason6410_fb_win0 = {
  75.     /* this is to ensure we use win0 */
  76.     .win_mode    = {
  77. #if 0
  78.         .pixclock     = 115440,
  79. #endif
  80.         .left_margin    = 0x03,
  81.         .right_margin = 0x02,
  82.         .upper_margin = 0x01,
  83.         .lower_margin = 0x01,
  84.         .hsync_len     = 0x28,
  85.         .vsync_len    = 0x01,
  86.         .xres         = 480,
  87.         .yres         = 272,
  88.     },
  89.     .max_bpp     = 32,
  90.     .default_bpp     = 16,
  91. };

  92. /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
  93. static struct s3c_fb_platdata jason6410_lcd_pdata __initdata = {
  94.     .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
  95.     .win[0]         = &jason6410_fb_win0,
  96.     .vidcon0     = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
  97.     .vidcon1     = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
  98. };

  99. /* Nand flash */
  100. static struct mtd_partition jason6410_nand_part[] = {
  101.     {
  102.         .name         = "u-boot-2011.06",
  103.         .offset         = 0,
  104.         .size         = (4 * 128 *SZ_1K),
  105.         .mask_flags     = MTD_CAP_NANDFLASH,
  106.     },
  107.     {
  108.         .name         = "Linux Kernel 3.2.8",
  109.         .offset         = MTDPART_OFS_APPEND,
  110.         .size         = (5*SZ_1M) ,
  111.         .mask_flags     = MTD_CAP_NANDFLASH,
  112.     },
  113.     {
  114.         .name         = "UBI File System",
  115.         .offset         = MTDPART_OFS_APPEND,
  116.         .size         = MTDPART_SIZ_FULL,
  117.     }
  118. };

  119. static struct s3c2410_nand_set jason6410_nand_sets[] = {
  120.     [0] = {
  121.         .name         = "nand",
  122.         .nr_chips     = 1,
  123.         .nr_partitions = ARRAY_SIZE(jason6410_nand_part),
  124.         .partitions     = jason6410_nand_part,
  125.     },
  126. };

  127. static struct s3c2410_platform_nand jason6410_nand_info = {
  128.     .tacls = 25,
  129.     .twrph0 = 55,
  130.     .twrph1   = 40,
  131.     .nr_sets    = ARRAY_SIZE(jason6410_nand_sets),
  132.     .sets      = jason6410_nand_sets,
  133. };

  134. static struct platform_device *jason6410_devices[] __initdata = {
  135.     &s3c_device_nand,
  136.     &s3c_device_i2c0,
  137.     &s3c_device_fb,
  138. };

  139. static struct i2c_board_info i2c_devs0[] __initdata = {
  140.     { I2C_BOARD_INFO("24c08", 0x50), },
  141. };

  142. static struct i2c_board_info i2c_devs1[] __initdata = {
  143.     /* Add your i2c device here */
  144. };

  145. static void __init jason6410_map_io(void)
  146. {
  147.     u32 tmp;

  148.     s3c64xx_init_io(NULL, 0);
  149.     s3c24xx_init_clocks(12000000);
  150.     s3c24xx_init_uarts(jason6410_uartcfgs, ARRAY_SIZE(jason6410_uartcfgs));

  151.     /* set the LCD type */
  152.     tmp = __raw_readl(S3C64XX_SPCON);
  153.     tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
  154.     tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
  155.     __raw_writel(tmp, S3C64XX_SPCON);

  156.     /* remove the lcd bypass */
  157.     tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
  158.     tmp &= ~MIFPCON_LCD_BYPASS;
  159.     __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
  160. }

  161. static void __init jason6410_machine_init(void)
  162. {
  163.     s3c_device_nand.name = "s3c6410-nand";
  164.     s3c_nand_set_platdata(&jason6410_nand_info);

  165.     s3c_i2c0_set_platdata(NULL);

  166.     s3c_fb_set_platdata(&jason6410_lcd_pdata);

  167.     if (ARRAY_SIZE(i2c_devs0)) {
  168.         i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
  169.     }
  170.     if (ARRAY_SIZE(i2c_devs1)) {
  171.         i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
  172.     }

  173.     platform_add_devices(jason6410_devices, ARRAY_SIZE(jason6410_devices));
  174. }

  175. MACHINE_START(JASON6410, "JASON6410")
  176.     /* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
  177.     .atag_offset     = 0x100,
  178.     .init_irq = s3c6410_init_irq,
  179.     .map_io         = jason6410_map_io,
  180.     .init_machine     = jason6410_machine_init,
  181.     .timer         = &s3c24xx_timer,
  182. 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\n");
  20.         return -EINVAL;
  21.     }
  22.  
  23.     //指向平台设备的平台数据
  24.     pd = pdev->dev.platform_data;
  25.     if (!pd) {
  26.         dev_err(dev, "no platform data specified\n");
  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\n");
  34.         return -ENOMEM;
  35.     }

  36.     dev_dbg(dev, "allocate new framebuffer %p\n", 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\n");
  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\n");
  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\n");
  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\n");
  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\n");
  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\n");
  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\n");
  103.         goto err_ioremap;
  104.     }

  105.     dev_dbg(dev, "got resources (regs %p), probing windows\n", 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\n", 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\n", 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\n");
  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\n");
  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\n");
  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\n");
  105.     
  106.     //8. 设置帧缓冲模式
  107.     s3c_fb_set_par(fbinfo);

  108.     dev_dbg(sfb->dev, "about to register framebuffer\n");

  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\n");
  115.         return ret;
  116.     }

  117.     dev_info(sfb->dev, "window %d: fb %s\n", 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.\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.
  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. }


三、内核配置


点击(此处)折叠或打开

  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

阅读(10956) | 评论(2) | 转发(4) |
给主人留下些什么吧!~~

Oliver_L_Oliver2014-03-28 18:44:25

好得很!

好喜儿2013-09-14 15:48:11

好文!