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,在我的机器上显示如下

[cpp] view plaincopy

  1. # cat /sys/class/graphics/fb0/fsl_disp_property
  2. 2-layer-fb-bg
  3. # cat /sys/class/graphics/fb1/fsl_disp_property
  4. 1-layer-fb
  5. # cat /sys/class/graphics/fb2/fsl_disp_property
  6. 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,使用如下命令:

[cpp] view plaincopy

  1. echo 1-layer-fb > /sys/class/graphics/fb0/fsl_disp_property
  2. 或者
  3. 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使用。

[cpp] view plaincopy

  1. MEM_BG_SYNC:fb0 -> DP (full plane) -> DC -> DI0
  2. MEM_FG_SYNC:fb2 -> DP (partial plane) -> DC -> DI0
  3. 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的显示通道如下:

[cpp] view plaincopy

  1. MEM_BG_SYNC: fb1 -> DP (full plane) -> DC -> DI0
  2. MEM_FG_SYNC: fb2 -> DP (partial plane) -> DC -> DI1
  3. MEM_DC_SYNC: fb0 -> DC -> DI0

通道交换代码

[cpp] view plaincopy

  1. swap_disp_chan
  2. 1673 static ssize_t swap_disp_chan(struct device *dev,
  3. 1674                   struct device_attribute *attr,
  4. 1675                   const char *buf, size_t count)
  5. 1676 {
  6. 1677     struct fb_info *info = dev_get_drvdata(dev);
  7. 1678     struct mxcfb_info *mxcfbi = (struct mxcfb_info *)info->par;
  8. 1679     struct mxcfb_info *fg_mxcfbi = NULL;
  9. 1680
  10. 1681     acquire_console_sem();
  11. 1682     /* swap only happen between DP-BG and DC, while DP-FG disable */
  12. 1683     if (((mxcfbi->ipu_ch == MEM_BG_SYNC) &&
  13. 1684          (strstr(buf, "1-layer-fb") != NULL)) ||
  14. 1685         ((mxcfbi->ipu_ch == MEM_DC_SYNC) &&
  15. 1686          (strstr(buf, "2-layer-fb-bg") != NULL))) {
  16. 1687         int i;
  17. 1688
  18. 1689         for (i = 0; i < num_registered_fb; i++) {
  19. 1690             fg_mxcfbi =
  20. 1691                 (struct mxcfb_info *)mxcfb_info[i]->par;
  21. 1692             if (fg_mxcfbi->ipu_ch == MEM_FG_SYNC)
  22. 1693                 break;
  23. 1694             else
  24. 1695                 fg_mxcfbi = NULL;
  25. 1696         }
  26. 1697         if (!fg_mxcfbi ||
  27. 1698             fg_mxcfbi->cur_blank == FB_BLANK_UNBLANK) {
  28. 1699             dev_err(dev,
  29. 1700                 "Can not switch while fb2(fb-fg) is on.\n");
  30. 1701             release_console_sem();
  31. 1702             return count;
  32. 1703         }
  33. 1704
  34. 1705         if (swap_channels(info) < 0)
  35. 1706             dev_err(dev, "Swap display channel failed.\n");
  36. 1707     }
  37. 1708
  38. 1709     release_console_sem();
  39. 1710     return count;
  40. 1711 }
  41. 1712 DEVICE_ATTR(fsl_disp_property, 644, show_disp_chan, swap_disp_chan);

1682~1686 只有fb0和fb1才会参与显示通道的交换,fb2只使用MEM_FG_SYNC
1705 调用swap_channels实现通道的切换

[cpp] view plaincopy

  1. swap_channels
  2. 545 static int swap_channels(struct fb_info *fbi)
  3. 546 {
  4. 547     int i;
  5. 548     int swap_mode;
  6. 549     ipu_channel_t ch_to;
  7. 550     struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi->par;
  8. 551     struct fb_info *fbi_to = NULL;
  9. 552     struct mxcfb_info *mxc_fbi_to;
  10. 553
  11. 554     /* what‘s the target channel? */
  12. 555     if (mxc_fbi_from->ipu_ch == MEM_BG_SYNC)
  13. 556         ch_to = MEM_DC_SYNC;
  14. 557     else
  15. 558         ch_to = MEM_BG_SYNC;
  16. 559
  17. 560     for (i = 0; i < num_registered_fb; i++) {
  18. 561         mxc_fbi_to =
  19. 562             (struct mxcfb_info *)mxcfb_info[i]->par;
  20. 563         if (mxc_fbi_to->ipu_ch == ch_to) {
  21. 564             fbi_to = mxcfb_info[i];
  22. 565             break;
  23. 566         }
  24. 567     }
  25. 568     if (fbi_to == NULL)
  26. 569         return -1;
  27. 570
  28. 571     ipu_clear_irq(mxc_fbi_from->ipu_ch_irq);
  29. 572     ipu_clear_irq(mxc_fbi_to->ipu_ch_irq);
  30. 573     ipu_free_irq(mxc_fbi_from->ipu_ch_irq, fbi);
  31. 574     ipu_free_irq(mxc_fbi_to->ipu_ch_irq, fbi_to);
  32. 575
  33. 576     if (mxc_fbi_from->cur_blank == FB_BLANK_UNBLANK) {
  34. 577         if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
  35. 578             swap_mode = BOTH_ON;
  36. 579         else
  37. 580             swap_mode = SRC_ON;
  38. 581     } else {
  39. 582         if (mxc_fbi_to->cur_blank == FB_BLANK_UNBLANK)
  40. 583             swap_mode = TGT_ON;
  41. 584         else
  42. 585             swap_mode = BOTH_OFF;
  43. 586     }
  44. 587
  45. 588     /* tvout di-1: for DC use UYVY, for DP use RGB */
  46. 589     if (mxc_fbi_from->ipu_di == 1 && ch_to == MEM_DC_SYNC) {
  47. 590         fbi->var.bits_per_pixel = 16;
  48. 591         fbi->var.nonstd = IPU_PIX_FMT_UYVY;
  49. 592     } else if (mxc_fbi_from->ipu_di == 1 && ch_to == MEM_BG_SYNC) {
  50. 593         fbi->var.nonstd = 0;
  51. 594     } else if (mxc_fbi_from->ipu_di == 0 && ch_to == MEM_DC_SYNC) {
  52. 595         fbi_to->var.nonstd = 0;
  53. 596     } else if (mxc_fbi_from->ipu_di == 0 && ch_to == MEM_BG_SYNC) {
  54. 597         fbi->var.bits_per_pixel = 16;
  55. 598         fbi->var.nonstd = IPU_PIX_FMT_UYVY;
  56. 599     }
  57. 600
  58. 601     switch (swap_mode) {
  59. 602     case BOTH_ON:
  60. 603         /* disable target->switch src->enable target */
  61. 604         _swap_channels(fbi, fbi_to, true);
  62. 605         break;
  63. 606     case SRC_ON:
  64. 607         /* just switch src */
  65. 608         _swap_channels(fbi, fbi_to, false);
  66. 609         break;
  67. 610     case TGT_ON:
  68. 611         /* just switch target */
  69. 612         _swap_channels(fbi_to, fbi, false);
  70. 613         break;
  71. 614     case BOTH_OFF:
  72. 615         /* switch directly, no more need to do */
  73. 616         mxc_fbi_to->ipu_ch = mxc_fbi_from->ipu_ch;
  74. 617         mxc_fbi_from->ipu_ch = ch_to;
  75. 618         i = mxc_fbi_from->ipu_ch_irq;
  76. 619         mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
  77. 620         mxc_fbi_to->ipu_ch_irq = i;
  78. 621         break;
  79. 622     default:
  80. 623         break;
  81. 624     }
  82. 625
  83. 626     if (ipu_request_irq(mxc_fbi_from->ipu_ch_irq, mxcfb_irq_handler, 0,
  84. 627         MXCFB_NAME, fbi) != 0) {
  85. 628         dev_err(fbi->device, "Error registering irq %d\n",
  86. 629             mxc_fbi_from->ipu_ch_irq);
  87. 630         return -EBUSY;
  88. 631     }
  89. 632     ipu_disable_irq(mxc_fbi_from->ipu_ch_irq);
  90. 633     if (ipu_request_irq(mxc_fbi_to->ipu_ch_irq, mxcfb_irq_handler, 0,
  91. 634         MXCFB_NAME, fbi_to) != 0) {
  92. 635         dev_err(fbi_to->device, "Error registering irq %d\n",
  93. 636             mxc_fbi_to->ipu_ch_irq);
  94. 637         return -EBUSY;
  95. 638     }
  96. 639     ipu_disable_irq(mxc_fbi_to->ipu_ch_irq);
  97. 640
  98. 641     return 0;
  99. 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

[cpp] view plaincopy

  1. swap_channels
  2. 504 static int _swap_channels(struct fb_info *fbi,
  3. 505               struct fb_info *fbi_to, bool both_on)
  4. 506 {
  5. 507     int retval, tmp;
  6. 508     ipu_channel_t old_ch;
  7. 509     struct mxcfb_info *mxc_fbi_from = (struct mxcfb_info *)fbi->par;
  8. 510     struct mxcfb_info *mxc_fbi_to = (struct mxcfb_info *)fbi_to->par;
  9. 511
  10. 512     if (both_on) {
  11. 513         ipu_disable_channel(mxc_fbi_to->ipu_ch, true);
  12. 514         ipu_uninit_channel(mxc_fbi_to->ipu_ch);
  13. 515     }
  14. 516
  15. 517     /* switch the mxc fbi parameters */
  16. 518     old_ch = mxc_fbi_from->ipu_ch;
  17. 519     mxc_fbi_from->ipu_ch = mxc_fbi_to->ipu_ch;
  18. 520     mxc_fbi_to->ipu_ch = old_ch;
  19. 521     tmp = mxc_fbi_from->ipu_ch_irq;
  20. 522     mxc_fbi_from->ipu_ch_irq = mxc_fbi_to->ipu_ch_irq;
  21. 523     mxc_fbi_to->ipu_ch_irq = tmp;
  22. 524
  23. 525     _setup_disp_channel1(fbi);
  24. 526     retval = _setup_disp_channel2(fbi);
  25. 527     if (retval)
  26. 528         return retval;
  27. 529
  28. 530     /* switch between dp and dc, disable old idmac, enable new idmac */
  29. 531     retval = ipu_swap_channel(old_ch, mxc_fbi_from->ipu_ch);
  30. 532     ipu_uninit_channel(old_ch);
  31. 533
  32. 534     if (both_on) {
  33. 535         _setup_disp_channel1(fbi_to);
  34. 536         retval = _setup_disp_channel2(fbi_to);
  35. 537         if (retval)
  36. 538             return retval;
  37. 539         ipu_enable_channel(mxc_fbi_to->ipu_ch);
  38. 540     }
  39. 541
  40. 542     return retval;
  41. 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配置。

[cpp] view plaincopy

  1. <pre></pre>
  2. <pre></pre>
  3. <pre></pre>
  4. <pre></pre>
  5. <pre></pre>
  6. <pre></pre>
时间: 2024-08-26 08:10:56

mx51的三个framebuffer,mxc_ipuv3_fb.c分析的相关文章

u-boot学习(三):u-boot源码分析

建立域模型和关系数据模型有着不同的出发点: 域模型: 由程序代码组成, 通过细化持久化类的的粒度可提高代码的可重用性, 简化编程 在没有数据冗余的情况下, 应该尽可能减少表的数目, 简化表之间的参照关系, 以便提高数据的访问速度 Hibernate 把持久化类的属性分为两种: 值(value)类型: 没有 OID, 不能被单独持久化, 生命周期依赖于所属的持久化类的对象的生命周期 实体(entity)类型: 有 OID, 可以被单独持久化, 有独立的生命周期(如果实体类型包含值类型,这个值类型就

三个工厂模式的分析

学习设计模式很长时间了,一直想把这些模式进行分类和总结,却不知道从哪里开始.发现工厂模式是一个系列,就从三个工厂模式说起吧. 首先来说简单工厂模式,以设计计算器为例分析这个模式,简单工厂模式抽象出了一个业务逻辑的父类,父类定义了定义了属性和方法,子运算类只需要重写运算方法即可,客户端负责输入和输出数据,运算工厂类决定实例化对象. 简单工厂类结构图: 简单工厂实现了业务逻辑和界面逻辑的分离,但是如果我们需要增加或减少计算器功能,需要修改运算工厂类,这不符合开放封闭原则,这个模式要慎重使用. 前边的

数据导入HBase最常用的三种方式及实践分析

数据导入HBase最常用的三种方式及实践分析         摘要:要使用Hadoop,需要将现有的各种类型的数据库或数据文件中的数据导入HBase.一般而言,有三种常见方式:使用HBase的API中的Put方法,使用HBase 的bulk load工具和使用定制的MapReduce Job方式.本文均有详细描述. [编者按]要使用Hadoop,数据合并至关重要,HBase应用甚广.一般而言,需要 针对不同情景模式将现有的各种类型的数据库或数据文件中的数据转入至HBase 中.常见方式为:使用H

软件工程问题和对三个软件特点的分析

一.对软件工程提出的问题 1.我们如何来开发软件以满足对软件日益增长的需求. 2.我们怎么做来维护数量不段增长的已有软件. 3.为什么说软件工程的发展可以在一定程度上解决软件危机的各种弊端. 4.每个软件企业遵循的软件开发过程都是一样的吗. 5.当需求不能一次搞清楚,且系统需求比较复杂时应选用哪种开发模型比较适合. 6.为什么需求分析特别重要. 7.为什么说需求过程是一个迭代过程. 8.需求分析的难点在哪里. 9..需求评审的作用是什么,为什么必须评审,评审的标准是什么. 二.三款软件及其特点分

linux内核数据包转发流程(三)网卡帧接收分析

[版权声明:转载请保留出处:blog.csdn.net/gentleliu.邮箱:shallnew*163.com] 每个cpu都有队列来处理接收到的帧,都有其数据结构来处理入口和出口流量,因此,不同cpu之间没有必要使用上锁机制,.此队列数据结构为softnet_data(定义在include/linux/netdevice.h中): /* * Incoming packets are placed on per-cpu queues so that * no locking is neede

Mysql Binlog 三种格式介绍及分析

一.Mysql Binlog格式介绍       Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在binlog中. 优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能.(相比row能节约多少性能与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条件的update操作,以及整表删除

嵌入式 Linux开发Kernel移植(三)——Kernel工程Makefile分析

嵌入式 Linux开发Kernel移植(三)--Kernel工程Makefile分析 本文选择三星发布的基于SMDKV210开发板的linux 2.6.35.7版本kernel. 一.Kernel Makefle体系简介 1.Kernel Makefile体系组成 Kernel Makefile体系包含Kconfig和Kbuild两个系统. Kconfig系统 Kconfig 对应的是内核配置阶段,make xxconfig就是在使用Kconfig系统.Kconfig由三部分组成: script

Neural Turing Machines-NTM系列(三)ntm-lasagne源码分析

Neural Turing Machines-NTM系列(三)ntm-lasagne源码分析 在NTM系列文章(二)中,我们已经成功运行了一个ntm工程的源代码.在这一章中,将对它的源码实现进行分析. 1.网络结构 1.1 模块结构图 在图中可以看到,输入的数据在经过NTM的处理之后,输出经过NTM操作后的,跟之前大小相同的数据块.来看下CopyTask的完整输出图: 图中右侧的Input是输入数据,Output是目标数据,Prediction是通过NTM网络预测出来的输出数据,可以看出预测数据

Mysql Binlog三种格式介绍及分析【转】

一.Mysql Binlog格式介绍       Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在binlog中. 优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能.(相比row能节约多少性能 与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条 件的update操作,以及整表