一、LCD驱动程序架构
1.裸机驱动代码分析
①LCD初始化:控制器初始化,端口初始化,指明帧缓冲
②LCD图形显示:将图形数据写入帧缓冲
2.帧缓冲体验
帧缓冲:内存中的一段区域,通过对内存的修改。LCD控制器从内存中获取数据,自动的控制LCD的显示。
将图片显示到lcd。
3.帧缓冲架构
/dev/fb0就是帧缓冲,字符设备
fbmem_init():
fb_ops:
fb_write:
info结构:
主要是fb_var_screeninfo、fb_fix_screeninfo、fb_ops三个结构体:
struct fb_var_screeninfo:主要记录用户可以修改的控制器的参数。
fb_fix_screeninfo:主要记录用户不可以修改的控制器的参数
fb_ops:底层硬件操作的函数指针
http://www.cnblogs.com/lishixian/articles/2999923.html
二、LCD驱动程序分析
s3c2410fb_init:
s3c2410fb_driver:
s3c24xxfb_probe:
s3c2410fb_map_vedio_memory:
分析到这里发现并没有设置帧缓冲的地址:
于是可以通过搜索帧地址来辨别,在哪个函数中实现。
s3c2410fb_set_lcdaddr:
但是如何知道调用顺序呢,可以在函数中调用dump_stack():
阅读(64) | 评论(0) | 转发(0) |
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
1.裸机驱动代码分析
①LCD初始化:控制器初始化,端口初始化,指明帧缓冲
②LCD图形显示:将图形数据写入帧缓冲
- void lcd_init()
- {
- lcd_port_init(); //初始化gpdcon和gpccon初始化
- lcd_control_init(); //时序初始化和帧缓冲初始化
-
- //打开LCD电源
- GPGCON |= 0b11<<8;
- LCDCON5 |= (1<<3);
- LCDCON1 |= 1;
- }
帧缓冲:内存中的一段区域,通过对内存的修改。LCD控制器从内存中获取数据,自动的控制LCD的显示。
- # cat tq2440.bin > /dev/fb0
3.帧缓冲架构
/dev/fb0就是帧缓冲,字符设备
fbmem_init():
- static int __init
- fbmem_init(void)
- {
- proc_create("fb", 0, NULL, &fb_proc_fops);
-
- if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) //注册设备文件,注册帧缓冲,fp_fops是操作函数集
- printk("unable to get major %d for fb devs\n", FB_MAJOR);
-
- fb_class = class_create(THIS_MODULE, "graphics");
- if (IS_ERR(fb_class)) {
- printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
- fb_class = NULL;
- }
- return 0;
- }
- static const struct file_operations fb_fops = {
- .owner = THIS_MODULE,
- .read = fb_read, //写入
- .write = fb_write,
- .unlocked_ioctl = fb_ioctl,
- #ifdef CONFIG_COMPAT
- .compat_ioctl = fb_compat_ioctl,
- #endif
- .mmap = fb_mmap,
- .open = fb_open,
- .release = fb_release,
- #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
- .get_unmapped_area = get_fb_unmapped_area,
- #endif
- #ifdef CONFIG_FB_DEFERRED_IO
- .fsync = fb_deferred_io_fsync,
- #endif
- };
- static ssize_t
- fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
- {
- unsigned long p = *ppos;
- struct inode *inode = file->f_path.dentry->d_inode;
- int fbidx = iminor(inode);
- struct fb_info *info = registered_fb[fbidx];
- u32 *buffer, *src;
- u32 __iomem *dst;
- int c, i, cnt = 0, err = 0;
- unsigned long total_size;
-
- if (!info || !info->screen_base)
- return -ENODEV;
-
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
-
- if (info->fbops->fb_write)
- return info->fbops->fb_write(info, buf, count, ppos);
-
- total_size = info->screen_size;
-
- if (total_size == 0)
- total_size = info->fix.smem_len;
-
- if (p > total_size)
- return -EFBIG;
-
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
-
- if (count + p > total_size) {
- .........各种info
- }
info结构:
- struct fb_info {
- int node;
- int flags;
- struct mutex lock; //控制io操作锁
- struct fb_var_screeninfo var;/*LCD可变参数*/
- struct fb_fix_screeninfo fix;/*LCD固定参数*/
- struct fb_monspecs monspecs; /*LCD显示器标准*/
- struct work_struct queue; /*帧缓冲事件队列*/
- struct fb_pixmap pixmap; /*图像硬件mapper*/
- struct fb_pixmap sprite; /*光标硬件mapper*/
- struct fb_cmap cmap; /*当前的颜色表*/
- struct fb_videomode *mode; /*当前的显示模式*/
-
- #ifdef CONFIG_FB_BACKLIGHT
- struct backlight_device *bl_dev;/*对应的背光设备*/
- struct mutex bl_curve_mutex;
- u8 bl_curve[FB_BACKLIGHT_LEVELS];/*背光调整*/
- #endif
- #ifdef CONFIG_FB_DEFERRED_IO
- struct delayed_work deferred_work;
- struct fb_deferred_io *fbdefio;
- #endif
-
- struct fb_ops *fbops; /*对底层硬件操作的函数指针*/
- struct device *device;
- struct device *dev; /*fb设备*/
- int class_flag;
- #ifdef CONFIG_FB_TILEBLITTING
- struct fb_tile_ops *tileops; /*图块Blitting*/
- #endif
- char __iomem *screen_base; /*虚拟基地址*/
- unsigned long screen_size; /*LCD IO映射的虚拟内存大小*/
- void *pseudo_palette; /*伪16色颜色表*/
- #define FBINFO_STATE_RUNNING 0
- #define FBINFO_STATE_SUSPENDED 1
- u32 state; /*LCD的挂起或恢复状态*/
- void *fbcon_par;
- void *par;
- };
struct fb_var_screeninfo:主要记录用户可以修改的控制器的参数。
- struct fb_var_screeninfo {
- __u32 xres; /* visible resolution */
- __u32 yres;
- __u32 xres_virtual; /* virtual resolution */
- __u32 yres_virtual;
- __u32 xoffset; /* offset from virtual to visible */
- __u32 yoffset; /* resolution */
-
- __u32 bits_per_pixel; /* guess what */每个像素的位数即BPP
- __u32 grayscale; /* != 0 Graylevels instead of colors */
-
- struct fb_bitfield red; /* bitfield in fb mem if true color, */
- struct fb_bitfield green; /* else only length is significant */
- struct fb_bitfield blue;
- struct fb_bitfield transp; /* transparency */
-
- __u32 nonstd; /* != 0 Non standard pixel format */
-
- __u32 activate; /* see FB_ACTIVATE_* */
-
- __u32 height; /* height of picture in mm */
- __u32 width; /* width of picture in mm */
-
- __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
-
- /* Timing: All values in pixclocks, except pixclock (of course) */
- __u32 pixclock; /* pixel clock in ps (pico seconds) */
- __u32 left_margin; /* time from sync to picture */
- __u32 right_margin; /* time from picture to sync */
- __u32 upper_margin; /* time from sync to picture */
- __u32 lower_margin;
- __u32 hsync_len; /* length of horizontal sync */
- __u32 vsync_len; /* length of vertical sync */
- __u32 sync; /* see FB_SYNC_* */
- __u32 vmode; /* see FB_VMODE_* */
- __u32 rotate; /* angle we rotate counter clockwise */
- __u32 reserved[5]; /* Reserved for future compatibility */
- };
- struct fb_fix_screeninfo {
- char id[16]; /* identification string eg "TT Builtin" */
- unsigned long smem_start; /* Start of frame buffer mem */
- /* (physical address) */
- __u32 smem_len; /* Length of frame buffer mem */
- __u32 type; /* see FB_TYPE_* */
- __u32 type_aux; /* Interleave for interleaved Planes */
- __u32 visual; /* see FB_VISUAL_* */
- __u16 xpanstep; /* zero if no hardware panning */
- __u16 ypanstep; /* zero if no hardware panning */
- __u16 ywrapstep; /* zero if no hardware ywrap */
- __u32 line_length; /* length of a line in bytes */
- unsigned long mmio_start; /* Start of Memory Mapped I/O */
- /* (physical address) */
- __u32 mmio_len; /* Length of Memory Mapped I/O */
- __u32 accel; /* Indicate to driver which */
- /* specific chip/card we have */
- __u16 reserved[3]; /* Reserved for future compatibility */
- };
- struct fb_ops {
- /* open/release and usage marking */
- struct module *owner;
- int (*fb_open)(struct fb_info *info, int user);
- int (*fb_release)(struct fb_info *info, int user);
-
- /* For framebuffers with strange non linear layouts or that do not
- * work with normal memory mapped access
- */
- ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
- size_t count, loff_t *ppos);
- ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos);
-
- /* checks var and eventually tweaks it to something supported,
- * DO NOT MODIFY PAR */
- int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
-
- /* set the video mode according to info->var */
- int (*fb_set_par)(struct fb_info *info);
-
- /* set color register */
- int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info);
-
- /* set color registers in batch */
- int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
-
- /* blank display */
- int (*fb_blank)(int blank, struct fb_info *info);
-
- /* pan display */
- int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
-
- /* Draws a rectangle */
- void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
- /* Copy data from area to another */
- void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
- /* Draws a image to the display */
- void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
-
- /* Draws cursor */
- int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
-
- /* Rotates the display */
- void (*fb_rotate)(struct fb_info *info, int angle);
-
- /* wait for blit idle, optional */
- int (*fb_sync)(struct fb_info *info);
-
- /* perform fb specific ioctl (optional) */
- int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
- unsigned long arg);
-
- /* Handle 32bit compat ioctl (optional) */
- int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
- unsigned long arg);
-
- /* perform fb specific mmap */
- int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
-
- /* save current hardware state */
- void (*fb_save_state)(struct fb_info *info);
-
- /* restore saved state */
- void (*fb_restore_state)(struct fb_info *info);
-
- /* get capability given var */
- void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
- struct fb_var_screeninfo *var);
- };
二、LCD驱动程序分析
s3c2410fb_init:
- int __init s3c2410fb_init(void)
- {
- int ret = platform_driver_register(&s3c2410fb_driver); //注册平台驱动设备
-
- if (ret == 0)
- ret = platform_driver_register(&s3c2412fb_driver);;
-
- return ret;
- }
- static struct platform_driver s3c2410fb_driver = {
- .probe = s3c2410fb_probe, //probe函数,里面调用了s3c24xxfb_probe
- .remove = s3c2410fb_remove,
- .suspend = s3c2410fb_suspend,
- .resume = s3c2410fb_resume,
- .driver = {
- .name = "s3c2410-lcd",
- .owner = THIS_MODULE,
- },
- };
- static int __init s3c24xxfb_probe(struct platform_device *pdev,
- enum s3c_drv_type drv_type)
- {
- struct s3c2410fb_info *info;
- struct s3c2410fb_display *display;
- struct fb_info *fbinfo;
- struct s3c2410fb_mach_info *mach_info;
- struct resource *res;
- int ret;
- int irq;
- int i;
- int size;
- u32 lcdcon1;
-
- mach_info = pdev->dev.platform_data;
- if (mach_info == NULL) {
- dev_err(&pdev->dev,
- "no platform data for lcd, cannot attach\n");
- return -EINVAL;
- }
-
- if (mach_info->default_display >= mach_info->num_displays) {
- dev_err(&pdev->dev, "default is %d but only %d displays\n",
- mach_info->default_display, mach_info->num_displays);
- return -EINVAL;
- }
-
- display = mach_info->displays + mach_info->default_display;
-
- irq = platform_get_irq(pdev, 0); //获取中断号
- if (irq < 0) {
- dev_err(&pdev->dev, "no irq for device\n");
- return -ENOENT;
- }
-
- fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev); //分配fb_info结构
- if (!fbinfo)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, fbinfo);
-
- info = fbinfo->par;
- info->dev = &pdev->dev;
- info->drv_type = drv_type;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取寄存器地址
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to get memory registers\n");
- ret = -ENXIO;
- goto dealloc_fb;
- }
-
- size = (res->end - res->start) + 1;
- info->mem = request_mem_region(res->start, size, pdev->name);
- if (info->mem == NULL) {
- dev_err(&pdev->dev, "failed to get memory region\n");
- ret = -ENOENT;
- goto dealloc_fb;
- }
-
- info->io = ioremap(res->start, size); //转化成虚拟地址
- if (info->io == NULL) {
- dev_err(&pdev->dev, "ioremap() of registers failed\n");
- ret = -ENXIO;
- goto release_mem;
- }
-
- info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE);
-
- dprintk("devinit\n");
-
- strcpy(fbinfo->fix.id, driver_name);
-
- /* Stop the video */ //初始化fbinfo结构
- lcdcon1 = readl(info->io + S3C2410_LCDCON1);
- writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
-
- fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
- fbinfo->fix.type_aux = 0;
- fbinfo->fix.xpanstep = 0;
- fbinfo->fix.ypanstep = 0;
- fbinfo->fix.ywrapstep = 0;
- fbinfo->fix.accel = FB_ACCEL_NONE;
-
- fbinfo->var.nonstd = 0;
- fbinfo->var.activate = FB_ACTIVATE_NOW;
- fbinfo->var.accel_flags = 0;
- fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
-
- fbinfo->fbops = &s3c2410fb_ops;
- fbinfo->flags = FBINFO_FLAG_DEFAULT;
- fbinfo->pseudo_palette = &info->pseudo_pal;
-
- for (i = 0; i < 256; i++)
- info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
-
- ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); //注册中断函数
- if (ret) {
- dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
- ret = -EBUSY;
- goto release_regs;
- }
-
- info->clk = clk_get(NULL, "lcd");
- if (!info->clk || IS_ERR(info->clk)) {
- printk(KERN_ERR "failed to get lcd clock source\n");
- ret = -ENOENT;
- goto release_irq;
- }
-
- clk_enable(info->clk);
- dprintk("got and enabled clock\n");
-
- msleep(1);
-
- /* find maximum required memory size for display */
- for (i = 0; i < mach_info->num_displays; i++) {
- unsigned long smem_len = mach_info->displays[i].xres;
-
- smem_len *= mach_info->displays[i].yres;
- smem_len *= mach_info->displays[i].bpp;
- smem_len >>= 3;
- if (fbinfo->fix.smem_len < smem_len)
- fbinfo->fix.smem_len = smem_len;
- }
-
- /* Initialize video memory */
- ret = s3c2410fb_map_video_memory(fbinfo); //为帧缓冲分配内存空间。同时使用了dma
- if (ret) {
- printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
- ret = -ENOMEM;
- goto release_clock;
- }
-
- dprintk("got video memory\n");
-
- fbinfo->var.xres = display->xres;
- fbinfo->var.yres = display->yres;
- fbinfo->var.bits_per_pixel = display->bpp;
-
- s3c2410fb_init_registers(fbinfo); //GPIO初始化
-
- s3c2410fb_check_var(&fbinfo->var, fbinfo); //设置fb_var_screeninfo
-
- ret = register_framebuffer(fbinfo); //注册帧缓冲-register_framebuffer
- if (ret < 0) {
- printk(KERN_ERR "Failed to register framebuffer device: %d\n",
- ret);
- goto free_video_memory;
- }
-
- /* create device files */
- ret = device_create_file(&pdev->dev, &dev_attr_debug);
- if (ret) {
- printk(KERN_ERR "failed to add debug attribute\n");
- }
-
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- fbinfo->node, fbinfo->fix.id);
-
- return 0;
-
- free_video_memory:
- s3c2410fb_unmap_video_memory(fbinfo);
- release_clock:
- clk_disable(info->clk);
- clk_put(info->clk);
- release_irq:
- free_irq(irq, info);
- release_regs:
- iounmap(info->io);
- release_mem:
- release_resource(info->mem);
- kfree(info->mem);
- dealloc_fb:
- platform_set_drvdata(pdev, NULL);
- framebuffer_release(fbinfo);
- return ret;
- }
- static int __init s3c2410fb_map_video_memory(struct fb_info *info)
- {
- struct s3c2410fb_info *fbi = info->par;
- dma_addr_t map_dma;
- unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
-
- dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
-
- info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
- &map_dma, GFP_KERNEL); //为帧缓冲分配内存空间。同时使用了dma
-
- if (info->screen_base) {
- /* prevent initial garbage on screen */
- dprintk("map_video_memory: clear %p:%08x\n",
- info->screen_base, map_size);
- memset(info->screen_base, 0x00, map_size);
-
- info->fix.smem_start = map_dma;
-
- dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n",
- info->fix.smem_start, info->screen_base, map_size);
- }
-
- return info->screen_base ? 0 : -ENOMEM;
- }
分析到这里发现并没有设置帧缓冲的地址:
于是可以通过搜索帧地址来辨别,在哪个函数中实现。
s3c2410fb_set_lcdaddr:
- static void s3c2410fb_set_lcdaddr(struct fb_info *info)
- {
- unsigned long saddr1, saddr2, saddr3;
- struct s3c2410fb_info *fbi = info->par;
- void __iomem *regs = fbi->io;
-
- saddr1 = info->fix.smem_start >> 1;
- saddr2 = info->fix.smem_start;
- saddr2 += info->fix.line_length * info->var.yres;
- saddr2 >>= 1;
-
- saddr3 = S3C2410_OFFSIZE(0) |
- S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff);
-
- dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
- dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
- dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
-
- writel(saddr1, regs + S3C2410_LCDSADDR1); //这里设置了帧缓冲的地址
- writel(saddr2, regs + S3C2410_LCDSADDR2);
- writel(saddr3, regs + S3C2410_LCDSADDR3);
- }
- Backtrace:
- [<c0049048>] (dump_backtrace+0x0/0x10c) from [<c0373fac>] (dump_stack+0x18/0x1c)
- r7:232f3302 r6:5bd42233 r5:00000000 r4:3a352944
- [<c0373f94>] (dump_stack+0x0/0x1c) from [<c01718c8>] (s3c2410fb_set_par+0x150/0x78c)
- [<c0171778>] (s3c2410fb_set_par+0x0/0x78c) from [<c016a578>] (fbcon_init+0x42c/0x4b8)
- [<c016a14c>] (fbcon_init+0x0/0x4b8) from [<c0185800>] (visual_init+0xb8/0x100)
- [<c0185748>] (visual_init+0x0/0x100) from [<c018a65c>] (take_over_console+0x1f4/0x3d8)
- r7:00000000 r6:c03a6c90 r5:c05a75a0 r4:00000019
- [<c018a468>] (take_over_console+0x0/0x3d8) from [<c0167050>] (fbcon_takeover+0x7c/0xd4)
- [<c0166fd4>] (fbcon_takeover+0x0/0xd4) from [<c016b1b0>] (fbcon_event_notify+0x768/0x7b0)
- r5:ffffffff r4:00000000
- [<c016aa48>] (fbcon_event_notify+0x0/0x7b0) from [<c0070784>] (notifier_call_chain+0x54/0x94)
- [<c0070730>] (notifier_call_chain+0x0/0x94) from [<c0070d08>] (__blocking_notifier_call_chain+0x54/0x6c)
- r9:c04b5008 r8:00000005 r7:ffffffff r6:c381dd98 r5:c04c5470
- r4:c04c547c
- [<c0070cb4>] (__blocking_notifier_call_chain+0x0/0x6c) from [<c0070d40>] (blocking_notifier_call_chain+0x20/0x28)
- r8:c3842a04 r7:00000000 r6:c0513120 r5:c3842800 r4:c381dd60
- [<c0070d20>] (blocking_notifier_call_chain+0x0/0x28) from [<c015fc48>] (fb_notifier_call_chain+0x1c/0x24)
- [<c015fc2c>] (fb_notifier_call_chain+0x0/0x24) from [<c0160cf0>] (register_framebuffer+0x154/0x1fc)
- [<c0160b9c>] (register_framebuffer+0x0/0x1fc) from [<c0014bbc>] (s3c24xxfb_probe+0x4c4/0x6fc)
- [<c00146f8>] (s3c24xxfb_probe+0x0/0x6fc) from [<c0014e20>] (s3c2410fb_probe+0x14/0x18)
- [<c0014e0c>] (s3c2410fb_probe+0x0/0x18) from [<c019369c>] (platform_drv_probe+0x20/0x24)
- [<c019367c>] (platform_drv_probe+0x0/0x24) from [<c0192694>] (driver_probe_device+0x8c/0x1a0)
- [<c0192608>] (driver_probe_device+0x0/0x1a0) from [<c019283c>] (__driver_attach+0x94/0x98)
- [<c01927a8>] (__driver_attach+0x0/0x98) from [<c0191f38>] (bus_for_each_dev+0x6c/0x98)
- r7:c01927a8 r6:c04c56b8 r5:c381de98 r4:00000000
- [<c0191ecc>] (bus_for_each_dev+0x0/0x98) from [<c0192514>] (driver_attach+0x20/0x28)
- r7:c04c56b8 r6:00000000 r5:c04c56b8 r4:c001fc68
- [<c01924f4>] (driver_attach+0x0/0x28) from [<c0191764>] (bus_add_driver+0xa4/0x244)
- [<c01916c0>] (bus_add_driver+0x0/0x244) from [<c0192b00>] (driver_register+0x74/0x15c)
- [<c0192a8c>] (driver_register+0x0/0x15c) from [<c0193a80>] (platform_driver_register+0x6c/0x88)
- r7:c381c000 r6:00000000 r5:c001fa50 r4:c001fc68
- [<c0193a14>] (platform_driver_register+0x0/0x88) from [<c0014e38>] (s3c2410fb_init+0x14/0x30)
- [<c0014e24>] (s3c2410fb_init+0x0/0x30) from [<c0044284>] (do_one_initcall+0x3c/0x1bc)
- [<c0044248>] (do_one_initcall+0x0/0x1bc) from [<c0008438>] (kernel_init+0x88/0xf4)
- [<c00083b0>] (kernel_init+0x0/0xf4) from [<c005a2e8>] (do_exit+0x0/0x620)
给主人留下些什么吧!~~
评论热议