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;
}
#endif
s3cfb_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.youkuaiyun.com/hclydao
版权没有,但是转载请保留此段声明
============================================