mx51的三个framebuffer,mxc_ipuv3_fb.c分析
转载:http://blog.csdn.net/jack_a8/article/details/43309169
mx51支持三个framebuffer:fb0, fb1, fb2
/dev/graphics/fb0,/dev/graphics/fb1:
一个作为系统的主framebuffer,另外一个作为TVOUT输出的framebuffer,缺省情况下,fb0做primary(也就是用来在primary LCD显示UI),fb1做secondary(也就是用来在TVOUT输出上显示数据)。
根据项目中的实际物理连接情况,如果primary LCD连接到disp0,那么使用缺省设置,如果primary LCD连接到disp1,那么就要在kernel启动参数中加入di1_primary。
/dev/graphics/fb2 :
用来实现overlay叠加,显示video数据的framebuffer,仅支持bpp16,数据格式是yuv422,可以在DP(Display Process)和来自MEM_BG_SYNC的数据进行合成,再传送到DC/DI。
在mxc framebuffer probe 时,第一个注册的mxc framebuffer (fb0 或者fb1,这个framebuffer作为主LCD的framebuffer)使用MEM_BG_SYNC,第二个注册的mxc framebuffer(fb0或者fb1,这个framebuffer作为TVOUT使用的framebuffer)使用MEM_DC_SYNC,最后一个注册的framebuffer(fb2)使用MEM_FG_SYNC。
MEM_BG_SYNC 和MEM_FG_SYNC都是mx5x ipu中独一无二的资源,这意味着每个通道只能被其中一个framebuffer占用。事实上MEM_DC_SYNC这个通道并不存在,只是用来表示直接连接到DC
注意这几个framebuffer中的数据并不是直连显示设备,中间可能还有MX51 IPU的DP处理单元,DP Unit负责对fb0 fb1 fb2过来的数据进行处理,包括颜色转换,图层合并,gamma处理以及光标处理后发送给DC->DI->显示设备
fsl 在/sys/class/graphics/fbx/ 下创建了一个fsl特定的属性文件fsl_disp_property,在我的机器上显示如下
- # cat /sys/class/graphics/fb0/fsl_disp_property
- 2-layer-fb-bg
- # cat /sys/class/graphics/fb1/fsl_disp_property
- 1-layer-fb
- # cat /sys/class/graphics/fb2/fsl_disp_property
- 2-layer-fb-fg
2-layer-fb-bg,表示fb0使用MEM_BG_SYNC通道,在IPU 的Display Process模块和MEM_FG_SYNC通道来的数据合并,再送入DC
1-layer-fb,表示fb1使用MEM_DC_SYNC通道,不经过Display Process模块,DC(Display Control)直接连接到DI(Display Interface)
2-layber-fb-fg,表示fb2使用MEM_FG_SYNC通道,在IPU的Display Process模块和MEM_BG_SYNC通道来的数据合并,再送入DC
应用层还可以修改/sys/class/graphics/fb0/fsl_disp_property和/sys/class/graphics/fb1/fsl_disp_property,使用如下命令:
- echo 1-layer-fb > /sys/class/graphics/fb0/fsl_disp_property
- 或者
- echo 2-layer-fb-bg > /sys/class/graphics/fb1/fsl_disp_property
注意,二者的作用是一样的,都会导致fb0和fb1交换显示通道,fsl引入这个属性的目的,就是给上层应用提供一个接口,使得应用层可以控制fb0 fb1使用MEM_BG_SYNC还是MEM_DC_SYNC通道,说到这里可能还是让人糊涂,为什么应用层要选择fb0 fb1的通道,这要先搞清楚MEM_BG_SYNC和MEM_DC_SYNC的区别。
imx51/imx53 IPU支持三种类型的显示通道:MEM_BG_SYNC, MEM_FG_SYNC和MEM_DC_SYNC,framebuffer只能通过三者之一传送数据,这些通道在物理上是唯一的,同一时间只能被一个framebuffer使用。
- MEM_BG_SYNC:fb0 -> DP (full plane) -> DC -> DI0
- MEM_FG_SYNC:fb2 -> DP (partial plane) -> DC -> DI0
- MEM_DC_SYNC:fb1 -> DC -> DI1
MEM_BG_SYNC和MEM_FG_SYNC会在DP进行合并处理,这个功能就是所谓的overlay。
正常情况下来自fb0的UI和来自fb2的video数据在DP合并后,送到DI0,我们就可以看到UI 浮在video上面的效果。但是当激活双屏的时候,一般希望video数据和UI 都送到后屏(也就是DI1),前屏只显示UI。这就需要fb1拥有MEM_BG_SYNC,此时需要交换fb1和fb0的显示通道如下:
- MEM_BG_SYNC: fb1 -> DP (full plane) -> DC -> DI0
- MEM_FG_SYNC: fb2 -> DP (partial plane) -> DC -> DI1
- MEM_DC_SYNC: fb0 -> DC -> DI0
通道交换代码
- swap_disp_chan
- 1673 static ssize_t swap_disp_chan(struct device *dev,
- 1674 struct device_attribute *attr,
- 1675 const char *buf, size_t count)
- 1676 {
- 1677 struct fb_info *info = dev_get_drvdata(dev);
- 1678 struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
- 1679 struct mxcfb_info *fg_mxcfbi = NULL;
- 1680
- 1681 acquire_console_sem();
- 1682 /* swap only happen between DP-BG and DC, while DP-FG disable */
- 1683 if (((mxcfbi->ipu_ch == MEM_BG_SYNC) &&
- 1684 (strstr(buf, "1-layer-fb") != NULL)) ||
- 1685 ((mxcfbi->ipu_ch == MEM_DC_SYNC) &&
- 1686 (strstr(buf, "2-layer-fb-bg") != NULL))) {
- 1687 int i;
- 1688
- 1689 for (i = 0; i < num_registered_fb; i++) {
- 1690 fg_mxcfbi =
- 1691 (struct mxcfb_info *)mxcfb_info[i]->par;
- 1692 if (fg_mxcfbi->ipu_ch == MEM_FG_SYNC)
- 1693 break;
- 1694 else
- 1695 fg_mxcfbi = NULL;
- 1696 }
- 1697 if (!fg_mxcfbi ||
- 1698 fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
- 1699 dev_err(dev,
- 1700 "Can not switch while fb2(fb-fg) is on.\n");
- 1701 release_console_sem();
- 1702 return count;
- 1703 }
- 1704
- 1705 if (swap_channels(info) < 0)
- 1706 dev_err(dev, "Swap display channel failed.\n");
- 1707 }
- 1708
- 1709 release_console_sem();
- 1710 return count;
- 1711 }
- 1712 DEVICE_ATTR(fsl_disp_property, 644, show_disp_chan, swap_disp_chan);
1682~1686 只有fb0和fb1才会参与显示通道的交换,fb2只使用MEM_FG_SYNC
1705 调用swap_channels实现通道的切换
- swap_channels
- 545 static int swap_channels(struct fb_info *fbi)
- 546 {
- 547 int i;
- 548 int swap_mode;
- 549 ipu_channel_t ch_to;
- 550 struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi->par;
- 551 struct fb_info *fbi_to = NULL;
- 552 struct mxcfb_info *mxc_fbi_to;
- 553
- 554 /* what's the target channel? */
- 555 if (mxc_fbi_from->ipu_ch == MEM_BG_SYNC)
- 556 ch_to = MEM_DC_SYNC;
- 557 else
- 558 ch_to = MEM_BG_SYNC;
- 559
- 560 for (i = 0; i < num_registered_fb; i++) {
- 561 mxc_fbi_to =
- 562 (struct mxcfb_info *)mxcfb_info[i]->par;
- 563 if (mxc_fbi_to->ipu_ch == ch_to) {
- 564 fbi_to = mxcfb_info[i];
- 565 break;
- 566 }
- 567 }
- 568 if (fbi_to == NULL)
- 569 return -1;
- 570
- 571 ipu_clear_irq(mxc_fbi_from->ipu_ch_irq);
- 572 ipu_clear_irq(mxc_fbi_to->ipu_ch_irq);
- 573 ipu_free_irq(mxc_fbi_from->ipu_ch_irq, fbi);
- 574 ipu_free_irq(mxc_fbi_to->ipu_ch_irq, fbi_to);
- 575
- 576 if (mxc_fbi_from->cur_blank == FB_BLANK_UNBLANK) {
- 577 if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
- 578 swap_mode = BOTH_ON;
- 579 else
- 580 swap_mode = SRC_ON;
- 581 } else {
- 582 if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
- 583 swap_mode = TGT_ON;
- 584 else
- 585 swap_mode = BOTH_OFF;
- 586 }
- 587
- 588 /* tvout di-1: for DC use UYVY, for DP use RGB */
- 589 if (mxc_fbi_from->ipu_di == 1 && ch_to == MEM_DC_SYNC) {
- 590 fbi->var.bits_per_pixel = 16;
- 591 fbi->var.nonstd = IPU_PIX_FMT_UYVY;
- 592 } else if (mxc_fbi_from->ipu_di == 1 && ch_to == MEM_BG_SYNC) {
- 593 fbi->var.nonstd = 0;
- 594 } else if (mxc_fbi_from->ipu_di == 0 && ch_to == MEM_DC_SYNC) {
- 595 fbi_to->var.nonstd = 0;
- 596 } else if (mxc_fbi_from->ipu_di == 0 && ch_to == MEM_BG_SYNC) {
- 597 fbi->var.bits_per_pixel = 16;
- 598 fbi->var.nonstd = IPU_PIX_FMT_UYVY;
- 599 }
- 600
- 601 switch (swap_mode) {
- 602 case BOTH_ON:
- 603 /* disable target->switch src->enable target */
- 604 _swap_channels(fbi, fbi_to, true);
- 605 break;
- 606 case SRC_ON:
- 607 /* just switch src */
- 608 _swap_channels(fbi, fbi_to, false);
- 609 break;
- 610 case TGT_ON:
- 611 /* just switch target */
- 612 _swap_channels(fbi_to, fbi, false);
- 613 break;
- 614 case BOTH_OFF:
- 615 /* switch directly, no more need to do */
- 616 mxc_fbi_to->ipu_ch = mxc_fbi_from->ipu_ch;
- 617 mxc_fbi_from->ipu_ch = ch_to;
- 618 i = mxc_fbi_from->ipu_ch_irq;
- 619 mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
- 620 mxc_fbi_to->ipu_ch_irq = i;
- 621 break;
- 622 default:
- 623 break;
- 624 }
- 625
- 626 if (ipu_request_irq(mxc_fbi_from->ipu_ch_irq, mxcfb_irq_handler, 0,
- 627 MXCFB_NAME, fbi) != 0) {
- 628 dev_err(fbi->device, "Error registering irq %d\n",
- 629 mxc_fbi_from->ipu_ch_irq);
- 630 return -EBUSY;
- 631 }
- 632 ipu_disable_irq(mxc_fbi_from->ipu_ch_irq);
- 633 if (ipu_request_irq(mxc_fbi_to->ipu_ch_irq, mxcfb_irq_handler, 0,
- 634 MXCFB_NAME, fbi_to) != 0) {
- 635 dev_err(fbi_to->device, "Error registering irq %d\n",
- 636 mxc_fbi_to->ipu_ch_irq);
- 637 return -EBUSY;
- 638 }
- 639 ipu_disable_irq(mxc_fbi_to->ipu_ch_irq);
- 640
- 641 return 0;
- 642 }
550 mxc_fbi_from 和字面意思一样,我们想要交换哪一个fb_info,也就是交换源
555~558 交换只发生在MEM_DC_SYNC和MEM_BG_SYNC之间,如果源fb的通道是MEM_BG_SYNC,那么我们希望交换为MEM_DC_SYNC,反之亦然。
560~567 找到目标通道坐在的framebuffer
576~586 swap_mode记录下source和dest framebuffer的blank状态
571~574 先释放from和to的ipu 通道中断号,因为IPU通道中断号也会随着通道一起交换
589~599 I have no idea
601~613 _swap_channels进行交换
614~620 如果fbi_from和fbi_to都处于BLANK状态,那么直接交换通道即可,注意通道中断号也需要交换,因为通道和通道中断号是一一对应的。
626~642 重新为fbi_from和fbi_to申请ipu irq,这里disable了irq,不过不要紧,当pan_display操作时,会使能ipu irq
- swap_channels
- 504 static int _swap_channels(struct fb_info *fbi,
- 505 struct fb_info *fbi_to, bool both_on)
- 506 {
- 507 int retval, tmp;
- 508 ipu_channel_t old_ch;
- 509 struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi->par;
- 510 struct mxcfb_info *mxc_fbi_to = (struct mxcfb_info *)fbi_to->par;
- 511
- 512 if (both_on) {
- 513 ipu_disable_channel(mxc_fbi_to->ipu_ch, true);
- 514 ipu_uninit_channel(mxc_fbi_to->ipu_ch);
- 515 }
- 516
- 517 /* switch the mxc fbi parameters */
- 518 old_ch = mxc_fbi_from->ipu_ch;
- 519 mxc_fbi_from->ipu_ch = mxc_fbi_to->ipu_ch;
- 520 mxc_fbi_to->ipu_ch = old_ch;
- 521 tmp = mxc_fbi_from->ipu_ch_irq;
- 522 mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
- 523 mxc_fbi_to->ipu_ch_irq = tmp;
- 524
- 525 _setup_disp_channel1(fbi);
- 526 retval = _setup_disp_channel2(fbi);
- 527 if (retval)
- 528 return retval;
- 529
- 530 /* switch between dp and dc, disable old idmac, enable new idmac */
- 531 retval = ipu_swap_channel(old_ch, mxc_fbi_from->ipu_ch);
- 532 ipu_uninit_channel(old_ch);
- 533
- 534 if (both_on) {
- 535 _setup_disp_channel1(fbi_to);
- 536 retval = _setup_disp_channel2(fbi_to);
- 537 if (retval)
- 538 return retval;
- 539 ipu_enable_channel(mxc_fbi_to->ipu_ch);
- 540 }
- 541
- 542 return retval;
- 543 }
504~505 函数有三个参数,@fbi是source,@fbi_to是dest,@both_on 布尔量为true 则@fbi_to为UNBLANK状态;false,则@fbi_to为BLANK状态。这里@fbi一定为UNBLANK状态,否则不会调用这个函数。
512~515 在交换之前,先销毁掉@fbi_to的channel
518~523 交换二者的通道和通道irq
525~528 交换完成后,设置disp通道的参数。
531~532 现在,通道号已经交换完成,但是还有一件事没有完成,我们知道DC通道1,5的控制寄存器DC_WR_CH_CONF_x中,配置着这个DC通道连接到哪一个DI,我们希望交换通道,但是不希望更改到DI的配置。ipu_swap_channel交换两个DC通道的DI配置。
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
- <pre></pre>
mx51的三个framebuffer,mxc_ipuv3_fb.c分析的更多相关文章
- Mysql Binlog 三种格式介绍及分析
一.Mysql Binlog格式介绍 Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...
- c#之冒泡排序的三种实现和性能分析
冒泡排序算法是我们经常见到的尤其是子一些笔试题中. 下面和大家讨论c#中的冒泡排序,笔者提供了三种解决方案,并且会分析各自的性能优劣. 第一种估计大家都掌握的,使用数据交换来实现,这种就不多说了,园子 ...
- 三种工厂模式的分析以及C++实现
三种工厂模式的分析以及C++实现 以下是我自己学习设计模式的思考总结. 简单工厂模式 简单工厂模式是工厂模式中最简单的一种,他可以用比较简单的方式隐藏创建对象的细节,一般只需要告诉工厂类所需要的类型, ...
- Mysql Binlog三种格式介绍及分析【转】
一.Mysql Binlog格式介绍 Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...
- Linux I2C驱动分析(三)----i2c_dev驱动和应用层分析 【转】
本文转载自:http://blog.chinaunix.net/uid-21558711-id-3959287.html 分类: LINUX 原文地址:Linux I2C驱动分析(三)----i2c_ ...
- Pandas学习(三)——NBA球员薪资分析
欢迎加入python学习交流群 667279387 学习笔记汇总 Pandas学习(一)–数据的导入 pandas学习(二)–双色球数据分析 pandas学习(三)–NAB球员薪资分析 pandas学 ...
- scala中ClassOf、asInstenceOf、isInstanceOf三个预定义方法分析
classOf.isInstanceOf.asInstanceOf三个预定义方法分析 Scala的三个预定义(predefined)方法,我们经常用到:它们用来感觉很简单, 但是里面还是隐藏了一些细节 ...
- C2B电商三种主要模式的分析_数据分析师
C2B电商三种主要模式的分析_数据分析师 在过去的一年中电商领域血雨腥风,尤其是天猫.京东.苏宁.当当.易讯等B2C电商打得不亦乐乎.而随着B2C领域竞争进入白热化阶段,C2B模式也在天猫" ...
- SQL优化(三)—— 索引、explain分析
SQL优化(三)—— 索引.explain分析 一.什么是索引 索引是一种排好序的快速查找的数据结构,它帮助数据库高效的查询数据 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据 ...
随机推荐
- QuickSwitchSVNClient,快速完成SVN Switch的工具
[开源]QuickSwitchSVNClient,快速完成SVN Switch的工具 在实际的开发中,我们一般使用SVN工具进行源代码的管理.在实际的产品开发中,根据项目的一些定制要求,往往需要对某一 ...
- C#基础之方法和参数
C#基础之方法和参数 接上一篇<C#基础之类型和成员基础以及常量.字段.属性> 实例方法.静态方法 C#中的方法分为两类,一种是属于对象(类型的实例)的,称之为实例方法,另一种是属于类型的 ...
- 使用DBUnit实现对数据库的测试
这是一个JavaProject,有关DBUnit用法详见本文测试用例 首先是用到的实体类User.java package com.jadyer.model; public class User { ...
- linux常见笔试题
一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 . 2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统. 3. Linux文件系统中每个文件用 i节点 来 ...
- React的生命周期
我们先来看一张图,其实看完这张图基本就懂了,如果还不懂,请继续往下看. getDefaultProps 执行过一次后,被创建的类会有缓存,映射的值会存在this.props,前提是这个prop不是父组 ...
- Oracle 数据备份、恢复以及导入时表空间不存在的解决方案
一.数据备份(导出) 1.exp命令导出dmp文件(exp -help查看帮助信息) 命令:exp username/userpasswd@192.168.99.199/orcl file=C:\jd ...
- PostScript学习:另一种缩写为PS的技术
1.前言 PostScript是一种编程语言,直译为"后处理脚本"[相对印刷过程而言],学名为页面描述语言.更为详细的解释见维基百科,以及其翻译版百度百科. 值得一提的是,Post ...
- linux面试题集锦3《转》
三.简答题: 1.简述Linux文件系统通过i节点把文件的逻辑结构和物理结构转换的工作过程. 参考答案: Linux通过i节点表将文件的逻辑结构和物理结构进行转换. i节点是一个64字节长的表,表中包 ...
- [UWP小白日记-10]程序启动屏(ios解锁既视感)
讲一下 微软爸爸的开发者大会2016又暴了个表达式动画和Windows.UI.Composition的API,好叼的样子. 官方示例库GitHub 目前是懵逼状态,好复杂.脑细胞已经在地府排队了. ( ...
- ext3学习小结
先介绍一下ext3和ext4的一些区别吧,初看ext4相对于ext3源码还是有很多不同的,ext4加入的define和create两个强大的类,ext4为了让源码容易看,特意将所有的类进行了defin ...