s5pv210 android hdmi与LCD异步显示之fb2多线程操作驱动修改
之前有一篇文章已经介绍过210 linux hdmi显示 android和处理现在是把系统自带的hdmi相关代码删除 使用之前linux上用到的hdmi代码显示输出 改为由fb2同步显示到hdmi 内核版本linux3.0.8
一般情况能进行多线程操作的只有fb0设备 虽然dev下有显示fb1-4的设备但不能多个线程进行操作 如果某一个线程需要对fb1-4进行操作需要在应用程序中加上如下代码
ret = ioctl(lcd_fd, FBIOGET_VSCREENINFO, &var ); if( ret < 0 ){ printf( "ioctl FBIOGET_VSCREENINFO failed\n"); return -1; } var.activate = FB_ACTIVATE_FORCE; var.yres_virtual = var.yres; ret = ioctl(lcd_fd, FBIOPUT_VSCREENINFO, &var ); if( ret < 0 ){ printf( "ioctl FBIOPUT_VSCREENINFO failed\n"); return -1; }每这样操作一次 就会导致对应的frambuffer地址发生变化 同时其它进程也会mmap失败 这里就需要对fb驱动作进行修改
主要修改文件为
drivers/video/samsung/s3cfb.c
首先是
s3cfb_alloc_framebuffer函数里只对default_win分配了framebuffer地址 修改为如下
#if 0 //modify by hclydao if (i == pdata->default_win) { if (s3cfb_map_video_memory(ctrl->fb[i])) { dev_err(ctrl->dev, "failed to map video memory " "for default window (%d)\n", i); ret = -ENOMEM; goto err_map_video_mem; } } #else if (s3cfb_map_video_memory(ctrl->fb[i])) { dev_err(ctrl->dev, "failed to map video memory " "for default window (%d)\n", i); ret = -ENOMEM; goto err_map_video_mem; } #endifs3cfb_set_par函数修改如下
static int s3cfb_set_par(struct fb_info *fb) { struct s3cfb_global *fbdev = platform_get_drvdata(to_platform_device(fb->device)); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); struct s3cfb_window *win = fb->par; dev_dbg(fbdev->dev, "[fb%d] set_par\n", win->id); #if 0 //modify by hclydao /* modify the fix info */ if (win->id != pdata->default_win) { fb->fix.line_length = fb->var.xres_virtual * fb->var.bits_per_pixel / 8; fb->fix.smem_len = fb->fix.line_length * fb->var.yres_virtual; s3cfb_map_video_memory(fb); } #endif s3cfb_set_win_params(fbdev, win->id); return 0; }s3cfb_open及s3cfb_release_window函数修改如下
static int s3cfb_open(struct fb_info *fb, int user) { struct s3cfb_global *fbdev = platform_get_drvdata(to_platform_device(fb->device)); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); struct s3cfb_window *win = fb->par; int ret = 0; mutex_lock(&fbdev->lock); //modify by hclydao //if (win->in_use && win->id != pdata->default_win) if (win->in_use && (win->id != pdata->default_win) && (win->id != 4)) ret = -EBUSY; else win->in_use++; mutex_unlock(&fbdev->lock); return ret; } static int s3cfb_release_window(struct fb_info *fb) { struct s3cfb_global *fbdev = platform_get_drvdata(to_platform_device(fb->device)); struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev); struct s3cfb_window *win = fb->par; //modify by hclydao //if (win->id != pdata->default_win) if ((win->id != pdata->default_win) && (win->id != 4)) { s3cfb_set_window(fbdev, win->id, 0); s3cfb_unmap_video_memory(fb); s3cfb_set_buffer_address(fbdev, win->id); } win->x = 0; win->y = 0; return 0; }因为我想用多个线程对fb2进行操作 而默认的default_win是2所以修改为如上
s3cfb_ioctl函数中case S3CFB_GET_LCD_ADDR:修改如下
/* get changing physical framebuffer address(because of double buffering) */ case S3CFB_GET_LCD_ADDR: #if 0 //modify by hclydao LCDControllerBase = (volatile unsigned int *)ioremap(0xf8000000,1024); framebuffer_addr = LCDControllerBase[0xa0/4 + (win->id)*2]; //LCDControllerBase = (volatile unsigned int *)ioremap(0xf80000a0,1024); //framebuffer_addr = LCDControllerBase[(win->id)*2]; iounmap(LCDControllerBase); dev_dbg(fbdev->dev, "framebuffer_addr: 0x%08x\n", framebuffer_addr); #else framebuffer_addr = (int)fix->smem_start; dev_dbg(fbdev->dev, "framebuffer_addr: 0x%08x\n", framebuffer_addr); #endif if (copy_to_user((void *)arg, &framebuffer_addr, sizeof(int))) return -EFAULT; break;s3cfb_probe函数中加一句
s3cfb_set_window(fbdev, pdata->default_win, 1); //add by hclydao s3cfb_set_window(fbdev, 4, 1);
其中还有一些细节没有修改 可能存在bug 这样修改后就能够通过多个线程对fb2进行操作了 这里暂时只作下笔记.
目前已经实现了hdmi与lcd的异步显示 可以通过app控制hdmi输出的图片 暂时只能显示固定图片
============================================
作者:hclydao
http://blog.csdn.net/hclydao
版权没有,但是转载请保留此段声明
============================================