完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
LCD硬件原理
lcd去显存里取出数据,然后作用到屏幕上。 一旦设置好了LCD控制器,一旦分配好了显存,就什么都不用管了,当数据写入显存后,剩下的自己会做好。 应用程序需要做获得的信息; 显存的基地址 一个像素的格式 这些信息得由驱动程序提供。 open函数 //在fb-test.c中 int main(int argc, char **argv) { int opt; int req_fb = 0; int req_pattern = 0; printf("fb-test %d.%d.%d (%s)n", VERSION, PATCHLEVEL, SUBLEVEL, VERSION_NAME); //...参数处理 fb_open(req_fb, &fb_info); //打开fb设置,获取fb_info结构体 do_fill_screen(&fb_info, req_pattern); return 0; } //在common.c中 void fb_open(int fb_num, struct fb_info *fb_info) { char str[64]; int fd,tty; tty = open("/dev/tty1", O_RDWR); if(ioctl(tty, KDSETMODE, KD_GRAPHICS) == -1) printf("Failed to set graphics mode on tty1n"); sprintf(str, "/dev/fb%d", fb_num); fd = open(str, O_RDWR); //这里打开/dev/fb0 ASSERT(fd >= 0); fb_info->fd = fd; IOCTL1(fd, FBIOGET_VSCREENINFO, &fb_info->var); //这里获取var信息 IOCTL1(fd, FBIOGET_FSCREENINFO, &fb_info->fix); //这里获取fix信息 printf("fb res %dx%d virtual %dx%d, line_len %d, bpp %dn", fb_info->var.xres, fb_info->var.yres, fb_info->var.xres_virtual, fb_info->var.yres_virtual, fb_info->fix.line_length, fb_info->var.bits_per_pixel); //这里映射了显存地址 void *ptr = mmap(0, fb_info->var.yres_virtual * fb_info->fix.line_length, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); ASSERT(ptr != MAP_FAILED); fb_info->ptr = ptr; } 对应的在驱动层的open里面 //fbmem.c中有注册fb文件结构体的代码 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, //这里注册了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 .llseek = default_llseek, }; static int fb_open(struct inode *inode, struct file *file) __acquires(&info->lock) __releases(&info->lock) { int fbidx = iminor(inode); //获取次设备号 struct fb_info *info; int res = 0; info = get_fb_info(fbidx); //从fbidx中获取注册的registered_fb,这个文件是在lcd_drv.c中注册的 if (!info) { request_module("fb%d", fbidx); info = get_fb_info(fbidx); if (!info) return -ENODEV; } if (IS_ERR(info)) return PTR_ERR(info); mutex_lock(&info->lock); if (!try_module_get(info->fbops->owner)) { res = -ENODEV; goto out; } file->private_data = info; //把fb_info保存在private_data中 if (info->fbops->fb_open) { //尝试打开设备 res = info->fbops->fb_open(info,1); if (res) module_put(info->fbops->owner); } #ifdef CONFIG_FB_DEFERRED_IO if (info->fbdefio) fb_deferred_io_open(info, inode, file); #endif out: mutex_unlock(&info->lock); if (res) put_fb_info(info); return res; } ioctl的驱动调用 在fbmem.c中的fb_ioctl: static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct fb_info *info = file_fb_info(file); //从次设备号获得fb_info,open时保存在private_data中,这两个会对比一下是否一致 if (!info) return -ENODEV; return do_fb_ioctl(info, cmd, arg); } static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct fb_ops *fb; struct fb_var_screeninfo var; struct fb_fix_screeninfo fix; struct fb_con2fbmap con2fb; struct fb_cmap cmap_from; struct fb_cmap_user cmap; struct fb_event event; struct fb_dmabuf_export dmaexp; void __user *argp = (void __user *)arg; long ret = 0; switch (cmd) { case FBIOGET_VSCREENINFO: if (!lock_fb_info(info)) return -ENODEV; var = info->var; //从fb_info中获得var unlock_fb_info(info); ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0; //传递给用户 break; case FBIOPUT_VSCREENINFO: //... break; case FBIOGET_FSCREENINFO: if (!lock_fb_info(info)) return -ENODEV; fix = info->fix; //从fb_info中获得fix unlock_fb_info(info); ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0; //传递给用户 break; case FBIOPUTCMAP: //... break; case FBIOGETCMAP: //... break; case FBIOPAN_DISPLAY: //... break; case FBIO_CURSOR: ret = -EINVAL; break; case FBIOGET_CON2FBMAP: //... break; case FBIOPUT_CON2FBMAP: //... break; case FBIOBLANK: //... break; case FBIOGET_DMABUF: //... break; default: //... } return ret; } mmap驱动中的调用 在fbmem.c中有fb_mmap函数: static int fb_mmap(struct file *file, struct vm_area_struct * vma) { struct fb_info *info = file_fb_info(file); //获取fb_info struct fb_ops *fb; unsigned long mmio_pgoff; unsigned long start; u32 len; //... /* * Ugh. This can be either the frame buffer mapping, or * if pgoff points past it, the mmio mapping. */ start = info->fix.smem_start; //显存的起始地址 len = info->fix.smem_len; //显存长度 mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; //.... vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); fb_pgprotect(file, vma, start); return vm_iomap_memory(vma, start, len); //返回给应用程序的映射空间 } 原作者:习惯就好zz |
|
相关推荐
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
569 浏览 0 评论
839 浏览 1 评论
737 浏览 1 评论
1957 浏览 1 评论
3204 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 08:44 , Processed in 1.363564 second(s), Total 71, Slave 53 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号