一、LCD驱动程序架构

1.裸机驱动代码分析

①LCD初始化:控制器初始化,端口初始化,指明帧缓冲

②LCD图形显示:将图形数据写入帧缓冲

  1. void lcd_init()
  2. {
  3. lcd_port_init();     //初始化gpdcon和gpccon初始化
  4. lcd_control_init();   //时序初始化和帧缓冲初始化
  5. //打开LCD电源
  6. GPGCON |= 0b11<<8;
  7. LCDCON5 |= (1<<3);
  8. LCDCON1 |= 1;
  9. }

2.帧缓冲体验

帧缓冲:内存中的一段区域,通过对内存的修改。LCD控制器从内存中获取数据,自动的控制LCD的显示。

  1. # cat tq2440.bin > /dev/fb0

将图片显示到lcd。



3.帧缓冲架构

/dev/fb0就是帧缓冲,字符设备

fbmem_init():

  1. static int __init
  2. fbmem_init(void)
  3. {
  4. proc_create("fb", 0, NULL, &fb_proc_fops);
  5. if (register_chrdev(FB_MAJOR,"fb",&fb_fops))                                                    //注册设备文件,注册帧缓冲,fp_fops是操作函数集
  6. printk("unable to get major %d for fb devs\n", FB_MAJOR);
  7. fb_class = class_create(THIS_MODULE, "graphics");
  8. if (IS_ERR(fb_class)) {
  9. printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
  10. fb_class = NULL;
  11. }
  12. return 0;
  13. }

fb_ops:

  1. static const struct file_operations fb_fops = {
  2. .owner =    THIS_MODULE,
  3. .read =        fb_read,                                        //写入
  4. .write =    fb_write,
  5. .unlocked_ioctl = fb_ioctl,
  6. #ifdef CONFIG_COMPAT
  7. .compat_ioctl = fb_compat_ioctl,
  8. #endif
  9. .mmap =        fb_mmap,
  10. .open =        fb_open,
  11. .release =    fb_release,
  12. #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
  13. .get_unmapped_area = get_fb_unmapped_area,
  14. #endif
  15. #ifdef CONFIG_FB_DEFERRED_IO
  16. .fsync =    fb_deferred_io_fsync,
  17. #endif
  18. };

fb_write:

  1. static ssize_t
  2. fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
  3. {
  4. unsigned long p = *ppos;
  5. struct inode *inode = file->f_path.dentry->d_inode;
  6. int fbidx = iminor(inode);
  7. struct fb_info *info = registered_fb[fbidx];
  8. u32 *buffer, *src;
  9. u32 __iomem *dst;
  10. int c, i, cnt = 0, err = 0;
  11. unsigned long total_size;
  12. if (!info || !info->screen_base)
  13. return -ENODEV;
  14. if (info->state != FBINFO_STATE_RUNNING)
  15. return -EPERM;
  16. if (info->fbops->fb_write)
  17. return info->fbops->fb_write(info, buf, count, ppos);
  18. total_size = info->screen_size;
  19. if (total_size == 0)
  20. total_size = info->fix.smem_len;
  21. if (p > total_size)
  22. return -EFBIG;
  23. if (count > total_size) {
  24. err = -EFBIG;
  25. count = total_size;
  26. }
  27. if (count + p > total_size) {
  28. .........各种info
  29. }



info结构:

  1. struct fb_info {
  2. int node;
  3. int flags;
  4. struct mutex lock;                                //控制io操作锁
  5. struct fb_var_screeninfo var;/*LCD可变参数*/
  6. struct fb_fix_screeninfo fix;/*LCD固定参数*/
  7. struct fb_monspecs monspecs; /*LCD显示器标准*/
  8. struct work_struct queue; /*帧缓冲事件队列*/
  9. struct fb_pixmap pixmap; /*图像硬件mapper*/
  10. struct fb_pixmap sprite; /*光标硬件mapper*/
  11. struct fb_cmap cmap; /*当前的颜色表*/
  12. struct fb_videomode *mode; /*当前的显示模式*/
  13. #ifdef CONFIG_FB_BACKLIGHT
  14. struct backlight_device *bl_dev;/*对应的背光设备*/
  15. struct mutex bl_curve_mutex;
  16. u8 bl_curve[FB_BACKLIGHT_LEVELS];/*背光调整*/
  17. #endif
  18. #ifdef CONFIG_FB_DEFERRED_IO
  19. struct delayed_work deferred_work;
  20. struct fb_deferred_io *fbdefio;
  21. #endif
  22. struct fb_ops *fbops; /*对底层硬件操作的函数指针*/
  23. struct device *device;
  24. struct device *dev; /*fb设备*/
  25. int class_flag;
  26. #ifdef CONFIG_FB_TILEBLITTING
  27. struct fb_tile_ops *tileops; /*图块Blitting*/
  28. #endif
  29. char __iomem *screen_base; /*虚拟基地址*/
  30. unsigned long screen_size; /*LCD IO映射的虚拟内存大小*/
  31. void *pseudo_palette; /*伪16色颜色表*/
  32. #define FBINFO_STATE_RUNNING 0
  33. #define FBINFO_STATE_SUSPENDED 1
  34. u32 state; /*LCD的挂起或恢复状态*/
  35. void *fbcon_par;
  36. void *par;
  37. };

主要是fb_var_screeninfo、fb_fix_screeninfo、fb_ops三个结构体:

struct fb_var_screeninfo:主要记录用户可以修改的控制器的参数。

  1. struct fb_var_screeninfo {
  2. __u32 xres;            /* visible resolution        */
  3. __u32 yres;
  4. __u32 xres_virtual;        /* virtual resolution        */
  5. __u32 yres_virtual;
  6. __u32 xoffset;            /* offset from virtual to visible */
  7. __u32 yoffset;            /* resolution            */
  8. __u32 bits_per_pixel;        /* guess what            */每个像素的位数即BPP
  9. __u32 grayscale;        /* != 0 Graylevels instead of colors */
  10. struct fb_bitfield red;        /* bitfield in fb mem if true color, */
  11. struct fb_bitfield green;    /* else only length is significant */
  12. struct fb_bitfield blue;
  13. struct fb_bitfield transp;    /* transparency            */
  14. __u32 nonstd;            /* != 0 Non standard pixel format */
  15. __u32 activate;            /* see FB_ACTIVATE_*        */
  16. __u32 height;            /* height of picture in mm */
  17. __u32 width;            /* width of picture in mm */
  18. __u32 accel_flags;        /* (OBSOLETE) see fb_info.flags */
  19. /* Timing: All values in pixclocks, except pixclock (of course) */
  20. __u32 pixclock;            /* pixel clock in ps (pico seconds) */
  21. __u32 left_margin;        /* time from sync to picture    */
  22. __u32 right_margin;        /* time from picture to sync    */
  23. __u32 upper_margin;        /* time from sync to picture    */
  24. __u32 lower_margin;
  25. __u32 hsync_len;        /* length of horizontal sync    */
  26. __u32 vsync_len;        /* length of vertical sync    */
  27. __u32 sync;            /* see FB_SYNC_*        */
  28. __u32 vmode;            /* see FB_VMODE_*        */
  29. __u32 rotate;            /* angle we rotate counter clockwise */
  30. __u32 reserved[5];        /* Reserved for future compatibility */
  31. };

fb_fix_screeninfo:主要记录用户不可以修改的控制器的参数

  1. struct fb_fix_screeninfo {
  2. char id[16];            /* identification string eg "TT Builtin" */
  3. unsigned long smem_start;    /* Start of frame buffer mem */
  4. /* (physical address) */
  5. __u32 smem_len;            /* Length of frame buffer mem */
  6. __u32 type;            /* see FB_TYPE_*        */
  7. __u32 type_aux;            /* Interleave for interleaved Planes */
  8. __u32 visual;            /* see FB_VISUAL_*        */
  9. __u16 xpanstep;            /* zero if no hardware panning */
  10. __u16 ypanstep;            /* zero if no hardware panning */
  11. __u16 ywrapstep;        /* zero if no hardware ywrap */
  12. __u32 line_length;        /* length of a line in bytes */
  13. unsigned long mmio_start;    /* Start of Memory Mapped I/O */
  14. /* (physical address) */
  15. __u32 mmio_len;            /* Length of Memory Mapped I/O */
  16. __u32 accel;            /* Indicate to driver which    */
  17. /* specific chip/card we have    */
  18. __u16 reserved[3];        /* Reserved for future compatibility */
  19. };

fb_ops:底层硬件操作的函数指针

  1. struct fb_ops {
  2. /* open/release and usage marking */
  3. struct module *owner;
  4. int (*fb_open)(struct fb_info *info, int user);
  5. int (*fb_release)(struct fb_info *info, int user);
  6. /* For framebuffers with strange non linear layouts or that do not
  7. * work with normal memory mapped access
  8. */
  9. ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
  10. size_t count, loff_t *ppos);
  11. ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
  12. size_t count, loff_t *ppos);
  13. /* checks var and eventually tweaks it to something supported,
  14. * DO NOT MODIFY PAR */
  15. int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
  16. /* set the video mode according to info->var */
  17. int (*fb_set_par)(struct fb_info *info);
  18. /* set color register */
  19. int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
  20. unsigned blue, unsigned transp, struct fb_info *info);
  21. /* set color registers in batch */
  22. int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
  23. /* blank display */
  24. int (*fb_blank)(int blank, struct fb_info *info);
  25. /* pan display */
  26. int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
  27. /* Draws a rectangle */
  28. void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
  29. /* Copy data from area to another */
  30. void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
  31. /* Draws a image to the display */
  32. void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
  33. /* Draws cursor */
  34. int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
  35. /* Rotates the display */
  36. void (*fb_rotate)(struct fb_info *info, int angle);
  37. /* wait for blit idle, optional */
  38. int (*fb_sync)(struct fb_info *info);
  39. /* perform fb specific ioctl (optional) */
  40. int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
  41. unsigned long arg);
  42. /* Handle 32bit compat ioctl (optional) */
  43. int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
  44. unsigned long arg);
  45. /* perform fb specific mmap */
  46. int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
  47. /* save current hardware state */
  48. void (*fb_save_state)(struct fb_info *info);
  49. /* restore saved state */
  50. void (*fb_restore_state)(struct fb_info *info);
  51. /* get capability given var */
  52. void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
  53. struct fb_var_screeninfo *var);
  54. };

http://www.cnblogs.com/lishixian/articles/2999923.html



二、LCD驱动程序分析

s3c2410fb_init:

  1. int __init s3c2410fb_init(void)
  2. {
  3. int ret = platform_driver_register(&s3c2410fb_driver);                        //注册平台驱动设备
  4. if (ret == 0)
  5. ret = platform_driver_register(&s3c2412fb_driver);;
  6. return ret;
  7. }

s3c2410fb_driver:

  1. static struct platform_driver s3c2410fb_driver = {
  2. .probe        = s3c2410fb_probe,                                                //probe函数,里面调用了s3c24xxfb_probe
  3. .remove        = s3c2410fb_remove,
  4. .suspend    = s3c2410fb_suspend,
  5. .resume        = s3c2410fb_resume,
  6. .driver        = {
  7. .name    = "s3c2410-lcd",
  8. .owner    = THIS_MODULE,
  9. },
  10. };

s3c24xxfb_probe:

  1. static int __init s3c24xxfb_probe(struct platform_device *pdev,
  2. enum s3c_drv_type drv_type)
  3. {
  4. struct s3c2410fb_info *info;
  5. struct s3c2410fb_display *display;
  6. struct fb_info *fbinfo;
  7. struct s3c2410fb_mach_info *mach_info;
  8. struct resource *res;
  9. int ret;
  10. int irq;
  11. int i;
  12. int size;
  13. u32 lcdcon1;
  14. mach_info = pdev->dev.platform_data;
  15. if (mach_info == NULL) {
  16. dev_err(&pdev->dev,
  17. "no platform data for lcd, cannot attach\n");
  18. return -EINVAL;
  19. }
  20. if (mach_info->default_display >= mach_info->num_displays) {
  21. dev_err(&pdev->dev, "default is %d but only %d displays\n",
  22. mach_info->default_display, mach_info->num_displays);
  23. return -EINVAL;
  24. }
  25. display = mach_info->displays + mach_info->default_display;
  26. irq = platform_get_irq(pdev, 0);                                                       //获取中断号
  27. if (irq < 0) {
  28. dev_err(&pdev->dev, "no irq for device\n");
  29. return -ENOENT;
  30. }
  31. fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev);                 //分配fb_info结构
  32. if (!fbinfo)
  33. return -ENOMEM;
  34. platform_set_drvdata(pdev, fbinfo);
  35. info = fbinfo->par;
  36. info->dev = &pdev->dev;
  37. info->drv_type = drv_type;
  38. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);                                   //获取寄存器地址
  39. if (res == NULL) {
  40. dev_err(&pdev->dev, "failed to get memory registers\n");
  41. ret = -ENXIO;
  42. goto dealloc_fb;
  43. }
  44. size = (res->end - res->start) + 1;
  45. info->mem = request_mem_region(res->start, size, pdev->name);
  46. if (info->mem == NULL) {
  47. dev_err(&pdev->dev, "failed to get memory region\n");
  48. ret = -ENOENT;
  49. goto dealloc_fb;
  50. }
  51. info->io = ioremap(res->start, size);                                                 //转化成虚拟地址
  52. if (info->io == NULL) {
  53. dev_err(&pdev->dev, "ioremap() of registers failed\n");
  54. ret = -ENXIO;
  55. goto release_mem;
  56. }
  57. info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE);
  58. dprintk("devinit\n");
  59. strcpy(fbinfo->fix.id, driver_name);
  60. /* Stop the video */                                                                   //初始化fbinfo结构
  61. lcdcon1 = readl(info->io + S3C2410_LCDCON1);
  62. writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
  63. fbinfo->fix.type     = FB_TYPE_PACKED_PIXELS;
  64. fbinfo->fix.type_aux     = 0;
  65. fbinfo->fix.xpanstep     = 0;
  66. fbinfo->fix.ypanstep     = 0;
  67. fbinfo->fix.ywrapstep     = 0;
  68. fbinfo->fix.accel     = FB_ACCEL_NONE;
  69. fbinfo->var.nonstd     = 0;
  70. fbinfo->var.activate     = FB_ACTIVATE_NOW;
  71. fbinfo->var.accel_flags = 0;
  72. fbinfo->var.vmode     = FB_VMODE_NONINTERLACED;
  73. fbinfo->fbops         = &s3c2410fb_ops;
  74. fbinfo->flags         = FBINFO_FLAG_DEFAULT;
  75. fbinfo->pseudo_palette = &info->pseudo_pal;
  76. for (i = 0; i < 256; i++)
  77. info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
  78. ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info);                      //注册中断函数
  79. if (ret) {
  80. dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
  81. ret = -EBUSY;
  82. goto release_regs;
  83. }
  84. info->clk = clk_get(NULL, "lcd");
  85. if (!info->clk || IS_ERR(info->clk)) {
  86. printk(KERN_ERR "failed to get lcd clock source\n");
  87. ret = -ENOENT;
  88. goto release_irq;
  89. }
  90. clk_enable(info->clk);
  91. dprintk("got and enabled clock\n");
  92. msleep(1);
  93. /* find maximum required memory size for display */
  94. for (i = 0; i < mach_info->num_displays; i++) {
  95. unsigned long smem_len = mach_info->displays[i].xres;
  96. smem_len *= mach_info->displays[i].yres;
  97. smem_len *= mach_info->displays[i].bpp;
  98. smem_len >>= 3;
  99. if (fbinfo->fix.smem_len < smem_len)
  100. fbinfo->fix.smem_len = smem_len;
  101. }
  102. /* Initialize video memory */
  103. ret = s3c2410fb_map_video_memory(fbinfo);                                                   //为帧缓冲分配内存空间。同时使用了dma
  104. if (ret) {
  105. printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
  106. ret = -ENOMEM;
  107. goto release_clock;
  108. }
  109. dprintk("got video memory\n");
  110. fbinfo->var.xres = display->xres;
  111. fbinfo->var.yres = display->yres;
  112. fbinfo->var.bits_per_pixel = display->bpp;
  113. s3c2410fb_init_registers(fbinfo);                                                           //GPIO初始化
  114. s3c2410fb_check_var(&fbinfo->var, fbinfo);                                                  //设置fb_var_screeninfo
  115. ret = register_framebuffer(fbinfo);                                                         //注册帧缓冲-register_framebuffer
  116. if (ret < 0) {
  117. printk(KERN_ERR "Failed to register framebuffer device: %d\n",
  118. ret);
  119. goto free_video_memory;
  120. }
  121. /* create device files */
  122. ret = device_create_file(&pdev->dev, &dev_attr_debug);
  123. if (ret) {
  124. printk(KERN_ERR "failed to add debug attribute\n");
  125. }
  126. printk(KERN_INFO "fb%d: %s frame buffer device\n",
  127. fbinfo->node, fbinfo->fix.id);
  128. return 0;
  129. free_video_memory:
  130. s3c2410fb_unmap_video_memory(fbinfo);
  131. release_clock:
  132. clk_disable(info->clk);
  133. clk_put(info->clk);
  134. release_irq:
  135. free_irq(irq, info);
  136. release_regs:
  137. iounmap(info->io);
  138. release_mem:
  139. release_resource(info->mem);
  140. kfree(info->mem);
  141. dealloc_fb:
  142. platform_set_drvdata(pdev, NULL);
  143. framebuffer_release(fbinfo);
  144. return ret;
  145. }

s3c2410fb_map_vedio_memory:

  1. static int __init s3c2410fb_map_video_memory(struct fb_info *info)
  2. {
  3. struct s3c2410fb_info *fbi = info->par;
  4. dma_addr_t map_dma;
  5. unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
  6. dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
  7. info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
  8. &map_dma, GFP_KERNEL);                                                      //为帧缓冲分配内存空间。同时使用了dma
  9. if (info->screen_base) {
  10. /* prevent initial garbage on screen */
  11. dprintk("map_video_memory: clear %p:%08x\n",
  12. info->screen_base, map_size);
  13. memset(info->screen_base, 0x00, map_size);
  14. info->fix.smem_start = map_dma;
  15. dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n",
  16. info->fix.smem_start, info->screen_base, map_size);
  17. }
  18. return info->screen_base ? 0 : -ENOMEM;
  19. }

分析到这里发现并没有设置帧缓冲的地址:

于是可以通过搜索帧地址来辨别,在哪个函数中实现。

s3c2410fb_set_lcdaddr:

  1. static void s3c2410fb_set_lcdaddr(struct fb_info *info)
  2. {
  3. unsigned long saddr1, saddr2, saddr3;
  4. struct s3c2410fb_info *fbi = info->par;
  5. void __iomem *regs = fbi->io;
  6. saddr1 = info->fix.smem_start >> 1;
  7. saddr2 = info->fix.smem_start;
  8. saddr2 += info->fix.line_length * info->var.yres;
  9. saddr2 >>= 1;
  10. saddr3 = S3C2410_OFFSIZE(0) |
  11. S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff);
  12. dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
  13. dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
  14. dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
  15. writel(saddr1, regs + S3C2410_LCDSADDR1);                                  //这里设置了帧缓冲的地址
  16. writel(saddr2, regs + S3C2410_LCDSADDR2);
  17. writel(saddr3, regs + S3C2410_LCDSADDR3);
  18. }

但是如何知道调用顺序呢,可以在函数中调用dump_stack():

  1. Backtrace:
  2. [<c0049048>] (dump_backtrace+0x0/0x10c) from [<c0373fac>] (dump_stack+0x18/0x1c)
  3. r7:232f3302 r6:5bd42233 r5:00000000 r4:3a352944
  4. [<c0373f94>] (dump_stack+0x0/0x1c) from [<c01718c8>] (s3c2410fb_set_par+0x150/0x78c)
  5. [<c0171778>] (s3c2410fb_set_par+0x0/0x78c) from [<c016a578>] (fbcon_init+0x42c/0x4b8)
  6. [<c016a14c>] (fbcon_init+0x0/0x4b8) from [<c0185800>] (visual_init+0xb8/0x100)
  7. [<c0185748>] (visual_init+0x0/0x100) from [<c018a65c>] (take_over_console+0x1f4/0x3d8)
  8. r7:00000000 r6:c03a6c90 r5:c05a75a0 r4:00000019
  9. [<c018a468>] (take_over_console+0x0/0x3d8) from [<c0167050>] (fbcon_takeover+0x7c/0xd4)
  10. [<c0166fd4>] (fbcon_takeover+0x0/0xd4) from [<c016b1b0>] (fbcon_event_notify+0x768/0x7b0)
  11. r5:ffffffff r4:00000000
  12. [<c016aa48>] (fbcon_event_notify+0x0/0x7b0) from [<c0070784>] (notifier_call_chain+0x54/0x94)
  13. [<c0070730>] (notifier_call_chain+0x0/0x94) from [<c0070d08>] (__blocking_notifier_call_chain+0x54/0x6c)
  14. r9:c04b5008 r8:00000005 r7:ffffffff r6:c381dd98 r5:c04c5470
  15. r4:c04c547c
  16. [<c0070cb4>] (__blocking_notifier_call_chain+0x0/0x6c) from [<c0070d40>] (blocking_notifier_call_chain+0x20/0x28)
  17. r8:c3842a04 r7:00000000 r6:c0513120 r5:c3842800 r4:c381dd60
  18. [<c0070d20>] (blocking_notifier_call_chain+0x0/0x28) from [<c015fc48>] (fb_notifier_call_chain+0x1c/0x24)
  19. [<c015fc2c>] (fb_notifier_call_chain+0x0/0x24) from [<c0160cf0>] (register_framebuffer+0x154/0x1fc)
  20. [<c0160b9c>] (register_framebuffer+0x0/0x1fc) from [<c0014bbc>] (s3c24xxfb_probe+0x4c4/0x6fc)
  21. [<c00146f8>] (s3c24xxfb_probe+0x0/0x6fc) from [<c0014e20>] (s3c2410fb_probe+0x14/0x18)
  22. [<c0014e0c>] (s3c2410fb_probe+0x0/0x18) from [<c019369c>] (platform_drv_probe+0x20/0x24)
  23. [<c019367c>] (platform_drv_probe+0x0/0x24) from [<c0192694>] (driver_probe_device+0x8c/0x1a0)
  24. [<c0192608>] (driver_probe_device+0x0/0x1a0) from [<c019283c>] (__driver_attach+0x94/0x98)
  25. [<c01927a8>] (__driver_attach+0x0/0x98) from [<c0191f38>] (bus_for_each_dev+0x6c/0x98)
  26. r7:c01927a8 r6:c04c56b8 r5:c381de98 r4:00000000
  27. [<c0191ecc>] (bus_for_each_dev+0x0/0x98) from [<c0192514>] (driver_attach+0x20/0x28)
  28. r7:c04c56b8 r6:00000000 r5:c04c56b8 r4:c001fc68
  29. [<c01924f4>] (driver_attach+0x0/0x28) from [<c0191764>] (bus_add_driver+0xa4/0x244)
  30. [<c01916c0>] (bus_add_driver+0x0/0x244) from [<c0192b00>] (driver_register+0x74/0x15c)
  31. [<c0192a8c>] (driver_register+0x0/0x15c) from [<c0193a80>] (platform_driver_register+0x6c/0x88)
  32. r7:c381c000 r6:00000000 r5:c001fa50 r4:c001fc68
  33. [<c0193a14>] (platform_driver_register+0x0/0x88) from [<c0014e38>] (s3c2410fb_init+0x14/0x30)
  34. [<c0014e24>] (s3c2410fb_init+0x0/0x30) from [<c0044284>] (do_one_initcall+0x3c/0x1bc)
  35. [<c0044248>] (do_one_initcall+0x0/0x1bc) from [<c0008438>] (kernel_init+0x88/0xf4)
  36. [<c00083b0>] (kernel_init+0x0/0xf4) from [<c005a2e8>] (do_exit+0x0/0x620)

LCD驱动程序架构和分析的更多相关文章

  1. LCD驱动程序之层次分析

    1.回顾字符设备驱动程序: 字符设备驱动编写的一般步骤: 1)主设备号 2)构造file_operations结构体体 .open = xxxx .read = xxxxx 3)register_ch ...

  2. [国嵌攻略][142][LCD驱动程序架构]

    LCD裸机驱动回顾 1.LCD初始化 1.1.控制器初始化 1.2.端口初始化 1.3.指明了帧缓冲 2.LCD图形显示 2.1.将图形数据写入帧缓冲 Linux帧缓冲体验 把图片转换成开发板屏对应的 ...

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

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

  4. 10. LCD驱动程序 ——框架分析

    引言: 由LCD的硬件原理及操作(可参看韦哥博客:第017课 LCD原理详解及裸机程序分析) 我们知道只要LCD控制器的相关寄存器正确配置好,就可以在LCD面板上显示framebuffer中的内容. ...

  5. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  6. LCD驱动程序编写

    学习目标:编写LCD驱动程序,熟悉根据芯片手册分析时序图,配置寄存器,并测试LCD程序. 一.LCD驱动程序编写 步骤: 1)分配fb_info结构体 2)设置fb_info结构体 a. 固定参数 b ...

  7. LCD驱动程序

    学习目标:熟悉TFT LCD的概念,分层驱动工作原理和程序编写. 一.LCD 概念 1.  显示器数据组织格式 1)一幅图像成为一帧,每帧由多行组成,每行由多个像素组成.每个像素的颜色由若干位表示,对 ...

  8. linux驱动由浅入深系列:高通sensor架构实例分析之三(adsp上报数据详解、校准流程详解)【转】

    本文转载自:https://blog.csdn.net/radianceblau/article/details/76180915 本系列导航: linux驱动由浅入深系列:高通sensor架构实例分 ...

  9. LCD驱动程序(一)

    LCD显示原理: 在JZ2440上,想要让LCD显示,需要几个部分1.LCD硬件 2.开发板上的LCD控制器 3.SDRAM内存存放数据FramBuffer 4.可能还需要一个调色板(实际上是一块内存 ...

随机推荐

  1. 启动kafka集群,关闭kafka集群脚本

    启动kafka集群,关闭kafka集群脚本 在$KAFKA_HOME/bin下新建如下脚本文件 start-kafka.sh #!/bin/bash BROKERS="mini41 mini ...

  2. vue项目打包之后原本好的样式变得不好了的原因分析

    这个主要是打包的过程将所有的css文件进行归类压缩,导致原先其他文件里的样式对当前的产生了影响,应该有同样的类名了.怎么改?要么改类名,要么用scope,scss的写法.

  3. ajax 封装(集中 认证、错误、请求loading处理)

    一.为什么要对 ajax 进行封装:    (在使用antd pro 开发项目时,里面默认是把请求进行了封装的,放在 utils/request.js 中.使用起来非常方便   https://pro ...

  4. ffmpeg+nginx-rtmp-module

    原址: https://www.cnblogs.com/cnsanshao/p/6370938.html另外: vlc播放器能播放rtsp协议 nginx安装和配置 模块下载 https://gith ...

  5. liunx 上无法kill 掉 redis服务

    要新学习一下redis 的哨兵服务,但是发现启动redis的时候,哨兵服务已经存在了,而且reids6379的服务也杀不死,就找到这样的参考方案 /etc/init.d/redis-server st ...

  6. Day 56 jquery

    一 .事件委托实例 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=&q ...

  7. HDU3449_Consumer

    这个是一个背包的变形题,很值得仔细体味 大致题意: 这个比普通背包多一个限制:再选每一类物品之前必须要先购买一个篮子来装,篮子有一定的价格,其他就和背包是一样的了 思路: 为了能够体现篮子的价值,我们 ...

  8. 插件化框架解读之四大组件调用原理-Service(三)下篇

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本文将继续通过Service调用原理来解读Replugin插件化 ...

  9. smb.conf免密登录文件

    # This is the main Samba configuration file. You should read the# smb.conf(5) manual page in order t ...

  10. mySQL学习入门教程——4.内置函数

    四.内置函数: 包括了字符串函数.数值函数.日期函数.流程控制函数.其他函数(获取数据库信息)... 一.字符串函数[比较常用,需要掌握]1. concat(s1,s2,...,sn)   #把传入的 ...